@@ -162,6 +162,32 @@ static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) {
162162 }
163163}
164164
165+ // / Check a subset of invocation options to determine whether the current
166+ // / context can safely be considered as stable.
167+ static bool areOptionsInStableDir (CowCompilerInvocation &BuildInvocation,
168+ const ArrayRef<StringRef> StableDirs) {
169+ const auto &HSOpts = BuildInvocation.getHeaderSearchOpts ();
170+ assert (isPathInStableDir (StableDirs, HSOpts.Sysroot ) &&
171+ " Sysroots differ between module dependencies and current TU" );
172+
173+ assert (isPathInStableDir (StableDirs, HSOpts.ResourceDir ) &&
174+ " ResourceDirs differ between module dependencies and current TU" );
175+
176+ for (const auto &Entry : HSOpts.UserEntries ) {
177+ if (!Entry.IgnoreSysRoot )
178+ continue ;
179+ if (!isPathInStableDir (StableDirs, Entry.Path ))
180+ return false ;
181+ }
182+
183+ for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes ) {
184+ if (!isPathInStableDir (StableDirs, SysPrefix.Prefix ))
185+ return false ;
186+ }
187+
188+ return true ;
189+ }
190+
165191static std::vector<std::string> splitString (std::string S, char Separator) {
166192 SmallVector<StringRef> Segments;
167193 StringRef (S).split (Segments, Separator, /* MaxSplit=*/ -1 , /* KeepEmpty=*/ false );
@@ -217,6 +243,25 @@ void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
217243 }
218244}
219245
246+ bool dependencies::isPathInStableDir (const ArrayRef<StringRef> Directories,
247+ const StringRef Input) {
248+ auto PathStartsWith = [](StringRef Prefix, StringRef Path) {
249+ auto PrefixIt = llvm::sys::path::begin (Prefix),
250+ PrefixEnd = llvm::sys::path::end (Prefix);
251+ for (auto PathIt = llvm::sys::path::begin (Path),
252+ PathEnd = llvm::sys::path::end (Path);
253+ PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) {
254+ if (*PrefixIt != *PathIt)
255+ return false ;
256+ }
257+ return PrefixIt == PrefixEnd;
258+ };
259+
260+ return any_of (Directories, [&](StringRef Dir) {
261+ return !Dir.empty () && PathStartsWith (Dir, Input);
262+ });
263+ }
264+
220265static CowCompilerInvocation
221266makeCommonInvocationForModuleBuild (CompilerInvocation CI) {
222267 CI.resetNonModularOptions ();
@@ -770,6 +815,17 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
770815
771816 MD.ID .ModuleName = M->getFullModuleName ();
772817 MD.IsSystem = M->IsSystem ;
818+
819+ // Start off with the assumption that this module is shareable when there
820+ // is a sysroot provided. As more dependencies are discovered, check if those
821+ // come from the provided shared directories.
822+ const llvm::SmallVector<StringRef> StableDirs = {
823+ MDC.ScanInstance .getHeaderSearchOpts ().Sysroot ,
824+ MDC.ScanInstance .getHeaderSearchOpts ().ResourceDir };
825+ MD.IsInStableDirectories =
826+ !StableDirs[0 ].empty () &&
827+ (llvm::sys::path::root_directory (StableDirs[0 ]) != StableDirs[0 ]);
828+
773829 // For modules which use export_as link name, the linked product that of the
774830 // corresponding export_as-named module.
775831 if (!M->UseExportAsModuleLinkName )
@@ -811,6 +867,12 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
811867 MDC.ScanInstance .getASTReader ()->visitInputFileInfos (
812868 *MF, /* IncludeSystem=*/ true ,
813869 [&](const serialization::InputFileInfo &IFI, bool IsSystem) {
870+ if (MD.IsInStableDirectories ) {
871+ auto FullFilePath = ASTReader::ResolveImportedPath (
872+ PathBuf, IFI.UnresolvedImportedFilename , MF->BaseDirectory );
873+ MD.IsInStableDirectories =
874+ isPathInStableDir (StableDirs, *FullFilePath);
875+ }
814876 if (!(IFI.TopLevel && IFI.ModuleMap ))
815877 return ;
816878 if (IFI.UnresolvedImportedFilenameAsRequested .ends_with (
@@ -878,6 +940,11 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
878940 }
879941
880942 MD.IgnoreCWD = IgnoreCWD;
943+ // Check provided input paths from the invocation for determining
944+ // IsInStableDirectories.
945+ if (MD.IsInStableDirectories )
946+ MD.IsInStableDirectories = areOptionsInStableDir (CI, StableDirs);
947+
881948 MDC.associateWithContextHash (CI, IgnoreCWD, MD);
882949
883950 // Finish the compiler invocation. Requires dependencies and the context hash.
@@ -929,8 +996,13 @@ void ModuleDepCollectorPP::addModulePrebuiltDeps(
929996 for (const Module *Import : M->Imports )
930997 if (Import->getTopLevelModule () != M->getTopLevelModule ())
931998 if (MDC.isPrebuiltModule (Import->getTopLevelModule ()))
932- if (SeenSubmodules.insert (Import->getTopLevelModule ()).second )
999+ if (SeenSubmodules.insert (Import->getTopLevelModule ()).second ) {
9331000 MD.PrebuiltModuleDeps .emplace_back (Import->getTopLevelModule ());
1001+ // Conservatively consider the module as not coming from stable
1002+ // directories, as transitive dependencies from the prebuilt module
1003+ // have not been determined.
1004+ MD.IsInStableDirectories = false ;
1005+ }
9341006}
9351007
9361008void ModuleDepCollectorPP::addAllSubmoduleDeps (
@@ -943,6 +1015,13 @@ void ModuleDepCollectorPP::addAllSubmoduleDeps(
9431015 });
9441016}
9451017
1018+ void ModuleDepCollectorPP::addOneModuleDep (const Module *M, const ModuleID ID,
1019+ ModuleDeps &MD) {
1020+ MD.ClangModuleDeps .push_back (ID);
1021+ if (MD.IsInStableDirectories )
1022+ MD.IsInStableDirectories = MDC.ModularDeps [M]->IsInStableDirectories ;
1023+ }
1024+
9461025void ModuleDepCollectorPP::addModuleDep (
9471026 const Module *M, ModuleDeps &MD,
9481027 llvm::DenseSet<const Module *> &AddedModules) {
@@ -951,7 +1030,7 @@ void ModuleDepCollectorPP::addModuleDep(
9511030 !MDC.isPrebuiltModule (Import)) {
9521031 if (auto ImportID = handleTopLevelModule (Import->getTopLevelModule ()))
9531032 if (AddedModules.insert (Import->getTopLevelModule ()).second )
954- MD. ClangModuleDeps . push_back ( *ImportID);
1033+ addOneModuleDep (Import-> getTopLevelModule (), *ImportID, MD );
9551034 }
9561035 }
9571036}
@@ -975,7 +1054,7 @@ void ModuleDepCollectorPP::addAffectingClangModule(
9751054 !MDC.isPrebuiltModule (Affecting)) {
9761055 if (auto ImportID = handleTopLevelModule (Affecting))
9771056 if (AddedModules.insert (Affecting).second )
978- MD. ClangModuleDeps . push_back ( *ImportID);
1057+ addOneModuleDep (Affecting, *ImportID, MD );
9791058 }
9801059 }
9811060}
0 commit comments