@@ -90,63 +90,140 @@ static bool checkHeaderSearchPaths(const HeaderSearchOptions &HSOpts,
90
90
91
91
using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
92
92
93
- // / A listener that collects the imported modules and optionally the input
94
- // / files.
93
+ // / A listener that collects the imported modules and the input
94
+ // / files. While visiting, collect vfsoverlays and file inputs that determine
95
+ // / whether prebuilt modules fully resolve in stable directories.
95
96
class PrebuiltModuleListener : public ASTReaderListener {
96
97
public:
97
98
PrebuiltModuleListener (PrebuiltModuleFilesT &PrebuiltModuleFiles,
98
99
llvm::SmallVector<std::string> &NewModuleFiles,
99
- PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap ,
100
+ PrebuiltModulesAttrsMap &PrebuiltModulesASTMap ,
100
101
const HeaderSearchOptions &HSOpts,
101
- const LangOptions &LangOpts, DiagnosticsEngine &Diags)
102
+ const LangOptions &LangOpts, DiagnosticsEngine &Diags,
103
+ const llvm::SmallVector<StringRef> &StableDirs)
102
104
: PrebuiltModuleFiles(PrebuiltModuleFiles),
103
105
NewModuleFiles (NewModuleFiles),
104
- PrebuiltModuleVFSMap(PrebuiltModuleVFSMap ), ExistingHSOpts(HSOpts),
105
- ExistingLangOpts(LangOpts), Diags(Diags) {}
106
+ PrebuiltModulesASTMap(PrebuiltModulesASTMap ), ExistingHSOpts(HSOpts),
107
+ ExistingLangOpts(LangOpts), Diags(Diags), StableDirs(StableDirs) {}
106
108
107
109
bool needsImportVisitation () const override { return true ; }
110
+ bool needsInputFileVisitation () override { return true ; }
111
+ bool needsSystemInputFileVisitation () override { return true ; }
108
112
113
+ // / Accumulate the modules are transitively depended on by the initial
114
+ // / prebuilt module.
109
115
void visitImport (StringRef ModuleName, StringRef Filename) override {
110
116
if (PrebuiltModuleFiles.insert ({ModuleName.str (), Filename.str ()}).second )
111
117
NewModuleFiles.push_back (Filename.str ());
118
+
119
+ auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace (Filename);
120
+ PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first ->second ;
121
+ if (PrebuiltMapEntry.second )
122
+ PrebuiltModule.setInStableDir (!StableDirs.empty ());
123
+
124
+ if (auto It = PrebuiltModulesASTMap.find (CurrentFile);
125
+ It != PrebuiltModulesASTMap.end () && CurrentFile != Filename)
126
+ PrebuiltModule.addDependent (It->getKey ());
127
+ }
128
+
129
+ // / For each input file discovered, check whether it's external path is in a
130
+ // / stable directory. Traversal is stopped if the current module is not
131
+ // / considered stable.
132
+ bool visitInputFile (StringRef FilenameAsRequested, StringRef Filename,
133
+ bool isSystem, bool isOverridden,
134
+ bool isExplicitModule) override {
135
+ if (StableDirs.empty ())
136
+ return false ;
137
+ auto PrebuiltEntryIt = PrebuiltModulesASTMap.find (CurrentFile);
138
+ if ((PrebuiltEntryIt == PrebuiltModulesASTMap.end ()) ||
139
+ (!PrebuiltEntryIt->second .isInStableDir ()))
140
+ return false ;
141
+
142
+ PrebuiltEntryIt->second .setInStableDir (
143
+ isPathInStableDir (StableDirs, Filename));
144
+ return PrebuiltEntryIt->second .isInStableDir ();
112
145
}
113
146
147
+ // / Update which module that is being actively traversed.
114
148
void visitModuleFile (StringRef Filename,
115
149
serialization::ModuleKind Kind) override {
150
+ // If the CurrentFile is not
151
+ // considered stable, update any of it's transitive dependents.
152
+ auto PrebuiltEntryIt = PrebuiltModulesASTMap.find (CurrentFile);
153
+ if ((PrebuiltEntryIt != PrebuiltModulesASTMap.end ()) &&
154
+ !PrebuiltEntryIt->second .isInStableDir ())
155
+ PrebuiltEntryIt->second .updateDependentsNotInStableDirs (
156
+ PrebuiltModulesASTMap);
116
157
CurrentFile = Filename;
117
158
}
118
159
160
+ // / Check the header search options for a given module when considering
161
+ // / if the module comes from stable directories.
162
+ bool ReadHeaderSearchOptions (const HeaderSearchOptions &HSOpts,
163
+ StringRef ModuleFilename,
164
+ StringRef SpecificModuleCachePath,
165
+ bool Complain) override {
166
+
167
+ auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace (CurrentFile);
168
+ PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first ->second ;
169
+ if (PrebuiltMapEntry.second )
170
+ PrebuiltModule.setInStableDir (!StableDirs.empty ());
171
+
172
+ if (PrebuiltModule.isInStableDir ())
173
+ PrebuiltModule.setInStableDir (areOptionsInStableDir (StableDirs, HSOpts));
174
+
175
+ return false ;
176
+ }
177
+
178
+ // / Accumulate vfsoverlays used to build these prebuilt modules.
119
179
bool ReadHeaderSearchPaths (const HeaderSearchOptions &HSOpts,
120
180
bool Complain) override {
121
- std::vector<std::string> VFSOverlayFiles = HSOpts.VFSOverlayFiles ;
122
- PrebuiltModuleVFSMap.try_emplace (CurrentFile, llvm::from_range,
123
- VFSOverlayFiles);
181
+
182
+ auto PrebuiltMapEntry = PrebuiltModulesASTMap.try_emplace (CurrentFile);
183
+ PrebuiltModuleASTAttrs &PrebuiltModule = PrebuiltMapEntry.first ->second ;
184
+ if (PrebuiltMapEntry.second )
185
+ PrebuiltModule.setInStableDir (!StableDirs.empty ());
186
+
187
+ PrebuiltModule.setVFS (
188
+ llvm::StringSet<>(llvm::from_range, HSOpts.VFSOverlayFiles ));
189
+
124
190
return checkHeaderSearchPaths (
125
191
HSOpts, ExistingHSOpts, Complain ? &Diags : nullptr , ExistingLangOpts);
126
192
}
127
193
128
194
private:
129
195
PrebuiltModuleFilesT &PrebuiltModuleFiles;
130
196
llvm::SmallVector<std::string> &NewModuleFiles;
131
- PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap ;
197
+ PrebuiltModulesAttrsMap &PrebuiltModulesASTMap ;
132
198
const HeaderSearchOptions &ExistingHSOpts;
133
199
const LangOptions &ExistingLangOpts;
134
200
DiagnosticsEngine &Diags;
135
201
std::string CurrentFile;
202
+ const llvm::SmallVector<StringRef> &StableDirs;
136
203
};
137
204
138
205
// / Visit the given prebuilt module and collect all of the modules it
139
206
// / transitively imports and contributing input files.
140
207
static bool visitPrebuiltModule (StringRef PrebuiltModuleFilename,
141
208
CompilerInstance &CI,
142
209
PrebuiltModuleFilesT &ModuleFiles,
143
- PrebuiltModuleVFSMapT &PrebuiltModuleVFSMap ,
210
+ PrebuiltModulesAttrsMap &PrebuiltModulesASTMap ,
144
211
DiagnosticsEngine &Diags) {
212
+
213
+ // Gather the set of stable directories to use as transitive dependencies are
214
+ // discovered.
215
+ llvm::SmallVector<StringRef> StableDirs;
216
+ std::string SysrootToUse (CI.getHeaderSearchOpts ().Sysroot );
217
+ if (!SysrootToUse.empty () &&
218
+ (llvm::sys::path::root_directory (SysrootToUse) != SysrootToUse))
219
+ StableDirs = {SysrootToUse, CI.getHeaderSearchOpts ().ResourceDir };
220
+
145
221
// List of module files to be processed.
146
222
llvm::SmallVector<std::string> Worklist;
147
- PrebuiltModuleListener Listener (ModuleFiles, Worklist, PrebuiltModuleVFSMap,
223
+
224
+ PrebuiltModuleListener Listener (ModuleFiles, Worklist, PrebuiltModulesASTMap,
148
225
CI.getHeaderSearchOpts (), CI.getLangOpts (),
149
- Diags);
226
+ Diags, StableDirs );
150
227
151
228
Listener.visitModuleFile (PrebuiltModuleFilename,
152
229
serialization::MK_ExplicitModule);
@@ -371,16 +448,18 @@ class DependencyScanningAction : public tooling::ToolAction {
371
448
auto *FileMgr = ScanInstance.createFileManager (FS);
372
449
ScanInstance.createSourceManager (*FileMgr);
373
450
374
- // Store the list of prebuilt module files into header search options. This
375
- // will prevent the implicit build to create duplicate modules and will
376
- // force reuse of the existing prebuilt module files instead.
377
- PrebuiltModuleVFSMapT PrebuiltModuleVFSMap;
451
+ // Store a mapping of prebuilt module files and their properties like header
452
+ // search options. This will prevent the implicit build to create duplicate
453
+ // modules and will force reuse of the existing prebuilt module files
454
+ // instead.
455
+ PrebuiltModulesAttrsMap PrebuiltModulesASTMap;
456
+
378
457
if (!ScanInstance.getPreprocessorOpts ().ImplicitPCHInclude .empty ())
379
458
if (visitPrebuiltModule (
380
459
ScanInstance.getPreprocessorOpts ().ImplicitPCHInclude ,
381
460
ScanInstance,
382
461
ScanInstance.getHeaderSearchOpts ().PrebuiltModuleFiles ,
383
- PrebuiltModuleVFSMap , ScanInstance.getDiagnostics ()))
462
+ PrebuiltModulesASTMap , ScanInstance.getDiagnostics ()))
384
463
return false ;
385
464
386
465
// Create the dependency collector that will collect the produced
@@ -410,7 +489,7 @@ class DependencyScanningAction : public tooling::ToolAction {
410
489
case ScanningOutputFormat::Full:
411
490
MDC = std::make_shared<ModuleDepCollector>(
412
491
Service, std::move (Opts), ScanInstance, Consumer, Controller,
413
- OriginalInvocation, std::move (PrebuiltModuleVFSMap ));
492
+ OriginalInvocation, std::move (PrebuiltModulesASTMap ));
414
493
ScanInstance.addDependencyCollector (MDC);
415
494
break ;
416
495
}
0 commit comments