@@ -103,10 +103,13 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
103103 }
104104};
105105
106- struct ModuleFile {
106+ // / Represents a reference to a module file (*.pcm).
107+ class ModuleFile {
108+ protected:
107109 ModuleFile (StringRef ModuleName, PathRef ModuleFilePath)
108110 : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
109111
112+ public:
110113 ModuleFile () = delete ;
111114
112115 ModuleFile (const ModuleFile &) = delete ;
@@ -128,21 +131,58 @@ struct ModuleFile {
128131 new (this ) ModuleFile (std::move (Other));
129132 return *this ;
130133 }
131-
132- ~ModuleFile () {
133- if (!ModuleFilePath.empty () && !DebugModulesBuilder)
134- llvm::sys::fs::remove (ModuleFilePath);
135- }
134+ virtual ~ModuleFile () = default ;
136135
137136 StringRef getModuleName () const { return ModuleName; }
138137
139138 StringRef getModuleFilePath () const { return ModuleFilePath; }
140139
141- private :
140+ protected :
142141 std::string ModuleName;
143142 std::string ModuleFilePath;
144143};
145144
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+
146186// ReusablePrerequisiteModules - stands for PrerequisiteModules for which all
147187// the required modules are built successfully. All the module files
148188// are owned by the modules builder.
@@ -171,9 +211,9 @@ class ReusablePrerequisiteModules : public PrerequisiteModules {
171211 std::string getAsString () const {
172212 std::string Result;
173213 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 () << " " ;
177217 }
178218 return Result;
179219 }
@@ -185,9 +225,9 @@ class ReusablePrerequisiteModules : public PrerequisiteModules {
185225 return BuiltModuleNames.contains (ModuleName);
186226 }
187227
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 ));
191231 }
192232
193233private:
@@ -265,7 +305,7 @@ bool IsModuleFilesUpToDate(
265305
266306// / Build a module file for module with `ModuleName`. The information of built
267307// / module file are stored in \param BuiltModuleFiles.
268- llvm::Expected<ModuleFile >
308+ llvm::Expected<std::shared_ptr<BuiltModuleFile> >
269309buildModuleFile (llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
270310 const GlobalCompilationDatabase &CDB, const ThreadsafeFS &TFS,
271311 const ReusablePrerequisiteModules &BuiltModuleFiles) {
@@ -340,7 +380,7 @@ buildModuleFile(llvm::StringRef ModuleName, PathRef ModuleUnitFileName,
340380 ModuleUnitFileName));
341381 }
342382
343- return ModuleFile{ ModuleName, Inputs.CompileCommand .Output } ;
383+ return BuiltModuleFile::make ( ModuleName, Inputs.CompileCommand .Output ) ;
344384}
345385
346386bool ReusablePrerequisiteModules::canReuse (
@@ -509,10 +549,51 @@ class ModulesBuilder::ModulesBuilderImpl {
509549 ReusablePrerequisiteModules &BuiltModuleFiles);
510550
511551private:
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+
512557 ModuleFileCache Cache;
513558 ModuleNameToSourceCache ProjectModulesCache;
514559};
515560
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+
516597llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile (
517598 PathRef RequiredSource, StringRef ModuleName, const ThreadsafeFS &TFS,
518599 CachingProjectModules &MDB, ReusablePrerequisiteModules &BuiltModuleFiles) {
@@ -532,6 +613,11 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
532613 return llvm::createStringError (
533614 llvm::formatv (" Don't get the module unit for module {0}" , ModuleName));
534615
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+
535621 // Get Required modules in topological order.
536622 auto ReqModuleNames = getAllRequiredModules (RequiredSource, MDB, ModuleName);
537623 for (llvm::StringRef ReqModuleName : ReqModuleNames) {
@@ -551,15 +637,14 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
551637
552638 std::string ReqFileName =
553639 MDB.getSourceForModuleName (ReqModuleName, RequiredSource);
554- llvm::Expected<ModuleFile > MF = buildModuleFile (
640+ llvm::Expected<std::shared_ptr<BuiltModuleFile> > MF = buildModuleFile (
555641 ReqModuleName, ReqFileName, getCDB (), TFS, BuiltModuleFiles);
556642 if (llvm::Error Err = MF.takeError ())
557643 return Err;
558644
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));
563648 }
564649
565650 return llvm::Error::success ();
0 commit comments