@@ -157,6 +157,32 @@ static void optimizeCWD(CowCompilerInvocation &BuildInvocation, StringRef CWD) {
157
157
}
158
158
}
159
159
160
+ // / Check a subset of invocation options to determine whether the current
161
+ // / context can safely be considered as stable.
162
+ static bool areOptionsInStableDir (CowCompilerInvocation &BuildInvocation,
163
+ const ArrayRef<StringRef> StableDirs) {
164
+ const auto &HSOpts = BuildInvocation.getHeaderSearchOpts ();
165
+ assert (isPathInStableDir (StableDirs, HSOpts.Sysroot ) &&
166
+ " Sysroots differ between module dependencies and current TU" );
167
+
168
+ assert (isPathInStableDir (StableDirs, HSOpts.ResourceDir ) &&
169
+ " ResourceDirs differ between module dependencies and current TU" );
170
+
171
+ for (const auto &Entry : HSOpts.UserEntries ) {
172
+ if (!Entry.IgnoreSysRoot )
173
+ continue ;
174
+ if (!isPathInStableDir (StableDirs, Entry.Path ))
175
+ return false ;
176
+ }
177
+
178
+ for (const auto &SysPrefix : HSOpts.SystemHeaderPrefixes ) {
179
+ if (!isPathInStableDir (StableDirs, SysPrefix.Prefix ))
180
+ return false ;
181
+ }
182
+
183
+ return true ;
184
+ }
185
+
160
186
static std::vector<std::string> splitString (std::string S, char Separator) {
161
187
SmallVector<StringRef> Segments;
162
188
StringRef (S).split (Segments, Separator, /* MaxSplit=*/ -1 , /* KeepEmpty=*/ false );
@@ -212,6 +238,25 @@ void dependencies::resetBenignCodeGenOptions(frontend::ActionKind ProgramAction,
212
238
}
213
239
}
214
240
241
+ bool dependencies::isPathInStableDir (const ArrayRef<StringRef> Directories,
242
+ const StringRef Input) {
243
+ auto PathStartsWith = [](StringRef Prefix, StringRef Path) {
244
+ auto PrefixIt = llvm::sys::path::begin (Prefix),
245
+ PrefixEnd = llvm::sys::path::end (Prefix);
246
+ for (auto PathIt = llvm::sys::path::begin (Path),
247
+ PathEnd = llvm::sys::path::end (Path);
248
+ PrefixIt != PrefixEnd && PathIt != PathEnd; ++PrefixIt, ++PathIt) {
249
+ if (*PrefixIt != *PathIt)
250
+ return false ;
251
+ }
252
+ return PrefixIt == PrefixEnd;
253
+ };
254
+
255
+ return any_of (Directories, [&](StringRef Dir) {
256
+ return !Dir.empty () && PathStartsWith (Dir, Input);
257
+ });
258
+ }
259
+
215
260
static CowCompilerInvocation
216
261
makeCommonInvocationForModuleBuild (CompilerInvocation CI) {
217
262
CI.resetNonModularOptions ();
@@ -698,6 +743,17 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
698
743
699
744
MD.ID .ModuleName = M->getFullModuleName ();
700
745
MD.IsSystem = M->IsSystem ;
746
+
747
+ // Start off with the assumption that this module is shareable when there
748
+ // is a sysroot provided. As more dependencies are discovered, check if those
749
+ // come from the provided shared directories.
750
+ const llvm::SmallVector<StringRef> StableDirs = {
751
+ MDC.ScanInstance .getHeaderSearchOpts ().Sysroot ,
752
+ MDC.ScanInstance .getHeaderSearchOpts ().ResourceDir };
753
+ MD.IsInStableDirectories =
754
+ !StableDirs[0 ].empty () &&
755
+ (llvm::sys::path::root_directory (StableDirs[0 ]) != StableDirs[0 ]);
756
+
701
757
// For modules which use export_as link name, the linked product that of the
702
758
// corresponding export_as-named module.
703
759
if (!M->UseExportAsModuleLinkName )
@@ -739,6 +795,12 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
739
795
MDC.ScanInstance .getASTReader ()->visitInputFileInfos (
740
796
*MF, /* IncludeSystem=*/ true ,
741
797
[&](const serialization::InputFileInfo &IFI, bool IsSystem) {
798
+ if (MD.IsInStableDirectories ) {
799
+ auto FullFilePath = ASTReader::ResolveImportedPath (
800
+ PathBuf, IFI.UnresolvedImportedFilename , MF->BaseDirectory );
801
+ MD.IsInStableDirectories =
802
+ isPathInStableDir (StableDirs, *FullFilePath);
803
+ }
742
804
if (!(IFI.TopLevel && IFI.ModuleMap ))
743
805
return ;
744
806
if (IFI.UnresolvedImportedFilenameAsRequested .ends_with (
@@ -780,6 +842,11 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
780
842
}
781
843
});
782
844
845
+ // Check provided input paths from the invocation for determining
846
+ // IsInStableDirectories.
847
+ if (MD.IsInStableDirectories )
848
+ MD.IsInStableDirectories = areOptionsInStableDir (CI, StableDirs);
849
+
783
850
MDC.associateWithContextHash (CI, IgnoreCWD, MD);
784
851
785
852
// Finish the compiler invocation. Requires dependencies and the context hash.
@@ -821,8 +888,13 @@ void ModuleDepCollectorPP::addModulePrebuiltDeps(
821
888
for (const Module *Import : M->Imports )
822
889
if (Import->getTopLevelModule () != M->getTopLevelModule ())
823
890
if (MDC.isPrebuiltModule (Import->getTopLevelModule ()))
824
- if (SeenSubmodules.insert (Import->getTopLevelModule ()).second )
891
+ if (SeenSubmodules.insert (Import->getTopLevelModule ()).second ) {
825
892
MD.PrebuiltModuleDeps .emplace_back (Import->getTopLevelModule ());
893
+ // Conservatively consider the module as not coming from stable
894
+ // directories, as transitive dependencies from the prebuilt module
895
+ // have not been determined.
896
+ MD.IsInStableDirectories = false ;
897
+ }
826
898
}
827
899
828
900
void ModuleDepCollectorPP::addAllSubmoduleDeps (
@@ -835,6 +907,13 @@ void ModuleDepCollectorPP::addAllSubmoduleDeps(
835
907
});
836
908
}
837
909
910
+ void ModuleDepCollectorPP::addOneModuleDep (const Module *M, const ModuleID ID,
911
+ ModuleDeps &MD) {
912
+ MD.ClangModuleDeps .push_back (ID);
913
+ if (MD.IsInStableDirectories )
914
+ MD.IsInStableDirectories = MDC.ModularDeps [M]->IsInStableDirectories ;
915
+ }
916
+
838
917
void ModuleDepCollectorPP::addModuleDep (
839
918
const Module *M, ModuleDeps &MD,
840
919
llvm::DenseSet<const Module *> &AddedModules) {
@@ -843,7 +922,7 @@ void ModuleDepCollectorPP::addModuleDep(
843
922
!MDC.isPrebuiltModule (Import)) {
844
923
if (auto ImportID = handleTopLevelModule (Import->getTopLevelModule ()))
845
924
if (AddedModules.insert (Import->getTopLevelModule ()).second )
846
- MD. ClangModuleDeps . push_back ( *ImportID);
925
+ addOneModuleDep (Import-> getTopLevelModule (), *ImportID, MD );
847
926
}
848
927
}
849
928
}
@@ -867,7 +946,7 @@ void ModuleDepCollectorPP::addAffectingClangModule(
867
946
!MDC.isPrebuiltModule (Affecting)) {
868
947
if (auto ImportID = handleTopLevelModule (Affecting))
869
948
if (AddedModules.insert (Affecting).second )
870
- MD. ClangModuleDeps . push_back ( *ImportID);
949
+ addOneModuleDep (Affecting, *ImportID, MD );
871
950
}
872
951
}
873
952
}
0 commit comments