@@ -103,10 +103,13 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
103
103
}
104
104
};
105
105
106
- struct ModuleFile {
106
+ // / Represents a reference to a module file (*.pcm).
107
+ class ModuleFile {
108
+ protected:
107
109
ModuleFile (StringRef ModuleName, PathRef ModuleFilePath)
108
110
: ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
109
111
112
+ public:
110
113
ModuleFile () = delete ;
111
114
112
115
ModuleFile (const ModuleFile &) = delete ;
@@ -128,21 +131,58 @@ struct ModuleFile {
128
131
new (this ) ModuleFile (std::move (Other));
129
132
return *this ;
130
133
}
131
-
132
- ~ModuleFile () {
133
- if (!ModuleFilePath.empty () && !DebugModulesBuilder)
134
- llvm::sys::fs::remove (ModuleFilePath);
135
- }
134
+ virtual ~ModuleFile () = default ;
136
135
137
136
StringRef getModuleName () const { return ModuleName; }
138
137
139
138
StringRef getModuleFilePath () const { return ModuleFilePath; }
140
139
141
- private :
140
+ protected :
142
141
std::string ModuleName;
143
142
std::string ModuleFilePath;
144
143
};
145
144
145
+ // / Represents a prebuilt module file which is not owned by us.
146
+ class PrebuiltModuleFile : public ModuleFile {
147
+ private:
148
+ // private class to make sure the class can only be constructed by member
149
+ // functions.
150
+ struct CtorTag {};
151
+
152
+ public:
153
+ PrebuiltModuleFile (StringRef ModuleName, PathRef ModuleFilePath, CtorTag)
154
+ : ModuleFile(ModuleName, ModuleFilePath) {}
155
+
156
+ static std::shared_ptr<PrebuiltModuleFile> make (StringRef ModuleName,
157
+ PathRef ModuleFilePath) {
158
+ return std::make_shared<PrebuiltModuleFile>(ModuleName, ModuleFilePath,
159
+ CtorTag{});
160
+ }
161
+ };
162
+
163
+ // / Represents a module file built by us. We're responsible to remove it.
164
+ class BuiltModuleFile : public ModuleFile {
165
+ private:
166
+ // private class to make sure the class can only be constructed by member
167
+ // functions.
168
+ struct CtorTag {};
169
+
170
+ public:
171
+ BuiltModuleFile (StringRef ModuleName, PathRef ModuleFilePath, CtorTag)
172
+ : ModuleFile(ModuleName, ModuleFilePath) {}
173
+
174
+ static std::shared_ptr<BuiltModuleFile> make (StringRef ModuleName,
175
+ PathRef ModuleFilePath) {
176
+ return std::make_shared<BuiltModuleFile>(ModuleName, ModuleFilePath,
177
+ CtorTag{});
178
+ }
179
+
180
+ virtual ~BuiltModuleFile () {
181
+ if (!ModuleFilePath.empty () && !DebugModulesBuilder)
182
+ llvm::sys::fs::remove (ModuleFilePath);
183
+ }
184
+ };
185
+
146
186
// ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
147
187
// the required modules are built successfully. All the module files
148
188
// are owned by the modules builder.
@@ -171,9 +211,9 @@ class ReusablePrerequisiteModules : public PrerequisiteModules {
171
211
std::string getAsString () const {
172
212
std::string Result;
173
213
llvm::raw_string_ostream OS (Result);
174
- for (const auto &ModuleFile : RequiredModules) {
175
- OS << " -fmodule-file=" << ModuleFile ->getModuleName () << " ="
176
- << ModuleFile ->getModuleFilePath () << " " ;
214
+ for (const auto &MF : RequiredModules) {
215
+ OS << " -fmodule-file=" << MF ->getModuleName () << " ="
216
+ << MF ->getModuleFilePath () << " " ;
177
217
}
178
218
return Result;
179
219
}
@@ -185,9 +225,9 @@ class ReusablePrerequisiteModules : public PrerequisiteModules {
185
225
return BuiltModuleNames.contains (ModuleName);
186
226
}
187
227
188
- void addModuleFile (std::shared_ptr<const ModuleFile> ModuleFile ) {
189
- BuiltModuleNames.insert (ModuleFile ->getModuleName ());
190
- RequiredModules.emplace_back (std::move (ModuleFile ));
228
+ void addModuleFile (std::shared_ptr<const ModuleFile> MF ) {
229
+ BuiltModuleNames.insert (MF ->getModuleName ());
230
+ RequiredModules.emplace_back (std::move (MF ));
191
231
}
192
232
193
233
private:
@@ -265,7 +305,7 @@ bool IsModuleFilesUpToDate(
265
305
266
306
// / Build a module file for module with `ModuleName`. The information of built
267
307
// / module file are stored in \param BuiltModuleFiles.
268
- llvm::Expected<ModuleFile >
308
+ llvm::Expected<std::shared_ptr<BuiltModuleFile> >
269
309
buildModuleFile (llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
270
310
const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS,
271
311
const ReusablePrerequisiteModules &BuiltModuleFiles) {
@@ -340,7 +380,7 @@ buildModuleFile(llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
340
380
ModuleUnitFileName));
341
381
}
342
382
343
- return ModuleFile{ ModuleName, Inputs.CompileCommand .Output } ;
383
+ return BuiltModuleFile::make ( ModuleName, Inputs.CompileCommand .Output ) ;
344
384
}
345
385
346
386
bool ReusablePrerequisiteModules::canReuse (
@@ -509,10 +549,51 @@ class ModulesBuilder::ModulesBuilderImpl {
509
549
ReusablePrerequisiteModules &BuiltModuleFiles);
510
550
511
551
private:
552
+ // / Try to get prebuilt module files from the compilation database.
553
+ void getPrebuiltModuleFile (StringRef ModuleName, PathRef ModuleUnitFileName,
554
+ const ThreadsafeFS &TFS,
555
+ ReusablePrerequisiteModules &BuiltModuleFiles);
556
+
512
557
ModuleFileCache Cache;
513
558
ModuleNameToSourceCache ProjectModulesCache;
514
559
};
515
560
561
+ void ModulesBuilder::ModulesBuilderImpl::getPrebuiltModuleFile (
562
+ StringRef ModuleName, PathRef ModuleUnitFileName, const ThreadsafeFS &TFS,
563
+ ReusablePrerequisiteModules &BuiltModuleFiles) {
564
+ auto Cmd = getCDB ().getCompileCommand (ModuleUnitFileName);
565
+ if (!Cmd)
566
+ return ;
567
+
568
+ ParseInputs Inputs;
569
+ Inputs.TFS = &TFS;
570
+ Inputs.CompileCommand = std::move (*Cmd);
571
+
572
+ IgnoreDiagnostics IgnoreDiags;
573
+ auto CI = buildCompilerInvocation (Inputs, IgnoreDiags);
574
+ if (!CI)
575
+ return ;
576
+
577
+ // We don't need to check if the module files are in ModuleCache or adding
578
+ // them to the module cache. As even if the module files are in the module
579
+ // cache, we still need to validate them. And it looks not helpful to add them
580
+ // to the module cache, since we may always try to get the prebuilt module
581
+ // files before building the module files by ourselves.
582
+ for (auto &[ModuleName, ModuleFilePath] :
583
+ CI->getHeaderSearchOpts ().PrebuiltModuleFiles ) {
584
+ if (BuiltModuleFiles.isModuleUnitBuilt (ModuleName))
585
+ continue ;
586
+
587
+ if (IsModuleFileUpToDate (ModuleFilePath, BuiltModuleFiles,
588
+ TFS.view (std::nullopt ))) {
589
+ log (" Reusing prebuilt module file {0} of module {1} for {2}" ,
590
+ ModuleFilePath, ModuleName, ModuleUnitFileName);
591
+ BuiltModuleFiles.addModuleFile (
592
+ PrebuiltModuleFile::make (ModuleName, ModuleFilePath));
593
+ }
594
+ }
595
+ }
596
+
516
597
llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile (
517
598
PathRef RequiredSource, StringRef ModuleName, const ThreadsafeFS &TFS,
518
599
CachingProjectModules &MDB, ReusablePrerequisiteModules &BuiltModuleFiles) {
@@ -532,6 +613,11 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
532
613
return llvm::createStringError (
533
614
llvm::formatv (" Don't get the module unit for module {0}" , ModuleName));
534
615
616
+ // / Try to get prebuilt module files from the compilation database first. This
617
+ // / helps to avoid building the module files that are already built by the
618
+ // / compiler.
619
+ getPrebuiltModuleFile (ModuleName, ModuleUnitFileName, TFS, BuiltModuleFiles);
620
+
535
621
// Get Required modules in topological order.
536
622
auto ReqModuleNames = getAllRequiredModules (RequiredSource, MDB, ModuleName);
537
623
for (llvm::StringRef ReqModuleName : ReqModuleNames) {
@@ -551,15 +637,14 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
551
637
552
638
std::string ReqFileName =
553
639
MDB.getSourceForModuleName (ReqModuleName, RequiredSource);
554
- llvm::Expected<ModuleFile > MF = buildModuleFile (
640
+ llvm::Expected<std::shared_ptr<BuiltModuleFile> > MF = buildModuleFile (
555
641
ReqModuleName, ReqFileName, getCDB (), TFS, BuiltModuleFiles);
556
642
if (llvm::Error Err = MF.takeError ())
557
643
return Err;
558
644
559
- log (" Built module {0} to {1}" , ReqModuleName, MF->getModuleFilePath ());
560
- auto BuiltModuleFile = std::make_shared<const ModuleFile>(std::move (*MF));
561
- Cache.add (ReqModuleName, BuiltModuleFile);
562
- BuiltModuleFiles.addModuleFile (std::move (BuiltModuleFile));
645
+ log (" Built module {0} to {1}" , ReqModuleName, (*MF)->getModuleFilePath ());
646
+ Cache.add (ReqModuleName, *MF);
647
+ BuiltModuleFiles.addModuleFile (std::move (*MF));
563
648
}
564
649
565
650
return llvm::Error::success ();
0 commit comments