Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
Show All 13 Lines | |||||
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" | #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" | ||||
#include "llvm/Support/BLAKE3.h" | #include "llvm/Support/BLAKE3.h" | ||||
#include "llvm/Support/StringSaver.h" | #include "llvm/Support/StringSaver.h" | ||||
using namespace clang; | using namespace clang; | ||||
using namespace tooling; | using namespace tooling; | ||||
using namespace dependencies; | using namespace dependencies; | ||||
static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, | static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts, const Module *M, | ||||
ASTReader &Reader, | CompilerInstance &CI) { | ||||
const serialization::ModuleFile &MF) { | |||||
// Only preserve search paths that were used during the dependency scan. | // Only preserve search paths that were used during the dependency scan. | ||||
std::vector<HeaderSearchOptions::Entry> Entries = Opts.UserEntries; | std::vector<HeaderSearchOptions::Entry> Entries = Opts.UserEntries; | ||||
Opts.UserEntries.clear(); | Opts.UserEntries.clear(); | ||||
llvm::BitVector SearchPathUsage(Entries.size()); | llvm::BitVector SearchPathUsage(Entries.size()); | ||||
llvm::DenseSet<const serialization::ModuleFile *> Visited; | llvm::DenseSet<const Module *> Visited; | ||||
std::function<void(const serialization::ModuleFile *)> VisitMF = | std::function<void(const Module *)> VisitM = [&](const Module *M) { | ||||
[&](const serialization::ModuleFile *MF) { | SearchPathUsage |= CI.SearchPathUsage[M->getTopLevelModuleName()]; | ||||
SearchPathUsage |= MF->SearchPathUsage; | Visited.insert(M); | ||||
Visited.insert(MF); | for (const Module *Import : M->Imports) | ||||
for (const serialization::ModuleFile *Import : MF->Imports) | |||||
if (!Visited.contains(Import)) | if (!Visited.contains(Import)) | ||||
VisitMF(Import); | VisitM(Import); | ||||
}; | }; | ||||
VisitMF(&MF); | VisitM(M); | ||||
for (auto Idx : SearchPathUsage.set_bits()) | for (auto Idx : SearchPathUsage.set_bits()) | ||||
Opts.UserEntries.push_back(Entries[Idx]); | Opts.UserEntries.push_back(Entries[Idx]); | ||||
} | } | ||||
static std::vector<std::string> splitString(std::string S, char Separator) { | static std::vector<std::string> splitString(std::string S, char Separator) { | ||||
SmallVector<StringRef> Segments; | SmallVector<StringRef> Segments; | ||||
StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false); | StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false); | ||||
▲ Show 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | for (const Module *M : | ||||
if (!MDC.isPrebuiltModule(M)) | if (!MDC.isPrebuiltModule(M)) | ||||
DirectModularDeps.insert(M); | DirectModularDeps.insert(M); | ||||
for (const Module *M : DirectModularDeps) { | for (const Module *M : DirectModularDeps) { | ||||
// A top-level module might not be actually imported as a module when | // A top-level module might not be actually imported as a module when | ||||
// -fmodule-name is used to compile a translation unit that imports this | // -fmodule-name is used to compile a translation unit that imports this | ||||
// module. In that case it can be skipped. The appropriate header | // module. In that case it can be skipped. The appropriate header | ||||
// dependencies will still be reported as expected. | // dependencies will still be reported as expected. | ||||
if (!M->getASTFile()) | if (M->getFullModuleName() == MDC.ScanInstance.getLangOpts().ModuleName) | ||||
continue; | continue; | ||||
handleTopLevelModule(M); | handleTopLevelModule(M); | ||||
} | } | ||||
MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); | MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts); | ||||
for (auto &&I : MDC.ModularDeps) | for (auto &&I : MDC.ModularDeps) | ||||
MDC.Consumer.handleModuleDependency(*I.second); | MDC.Consumer.handleModuleDependency(*I.second); | ||||
Show All 13 Lines | ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) { | ||||
if (!ModI.second) | if (!ModI.second) | ||||
return ModI.first->second->ID; | return ModI.first->second->ID; | ||||
ModI.first->second = std::make_unique<ModuleDeps>(); | ModI.first->second = std::make_unique<ModuleDeps>(); | ||||
ModuleDeps &MD = *ModI.first->second; | ModuleDeps &MD = *ModI.first->second; | ||||
MD.ID.ModuleName = M->getFullModuleName(); | MD.ID.ModuleName = M->getFullModuleName(); | ||||
MD.ImportedByMainFile = DirectModularDeps.contains(M); | MD.ImportedByMainFile = DirectModularDeps.contains(M); | ||||
MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName()); | |||||
MD.IsSystem = M->IsSystem; | MD.IsSystem = M->IsSystem; | ||||
ModuleMap &ModMapInfo = | ModuleMap &ModMapInfo = | ||||
MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); | MDC.ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); | ||||
Optional<FileEntryRef> ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M); | Optional<FileEntryRef> ModuleMap = ModMapInfo.getModuleMapFileForUniquing(M); | ||||
if (ModuleMap) { | if (ModuleMap) { | ||||
SmallString<128> Path = ModuleMap->getNameAsRequested(); | SmallString<128> Path = ModuleMap->getNameAsRequested(); | ||||
ModMapInfo.canonicalizeModuleMapPath(Path); | ModMapInfo.canonicalizeModuleMapPath(Path); | ||||
MD.ClangModuleMapFile = std::string(Path); | MD.ClangModuleMapFile = std::string(Path); | ||||
} | } | ||||
serialization::ModuleFile *MF = | for (const auto &E : MDC.ScanInstance.SortedFiles[M->getFullModuleName()]) { | ||||
MDC.ScanInstance.getASTReader()->getModuleManager().lookup( | |||||
M->getASTFile()); | |||||
MDC.ScanInstance.getASTReader()->visitInputFiles( | |||||
*MF, true, true, [&](const serialization::InputFile &IF, bool isSystem) { | |||||
// __inferred_module.map is the result of the way in which an implicit | // __inferred_module.map is the result of the way in which an implicit | ||||
// module build handles inferred modules. It adds an overlay VFS with | // module build handles inferred modules. It adds an overlay VFS with | ||||
// this file in the proper directory and relies on the rest of Clang to | // this file in the proper directory and relies on the rest of Clang to | ||||
// handle it like normal. With explicitly built modules we don't need | // handle it like normal. With explicitly built modules we don't need | ||||
// to play VFS tricks, so replace it with the correct module map. | // to play VFS tricks, so replace it with the correct module map. | ||||
if (IF.getFile()->getName().endswith("__inferred_module.map")) { | if (E.FE->getName().endswith("__inferred_module.map")) { | ||||
MDC.addFileDep(MD, ModuleMap->getName()); | MDC.addFileDep(MD, ModuleMap->getName()); | ||||
return; | continue; | ||||
} | |||||
MDC.addFileDep(MD, E.FE->getName()); | |||||
} | } | ||||
MDC.addFileDep(MD, IF.getFile()->getName()); | |||||
}); | |||||
llvm::DenseSet<const Module *> SeenDeps; | llvm::DenseSet<const Module *> SeenDeps; | ||||
addAllSubmodulePrebuiltDeps(M, MD, SeenDeps); | addAllSubmodulePrebuiltDeps(M, MD, SeenDeps); | ||||
addAllSubmoduleDeps(M, MD, SeenDeps); | addAllSubmoduleDeps(M, MD, SeenDeps); | ||||
addAllAffectingClangModules(M, MD, SeenDeps); | addAllAffectingClangModules(M, MD, SeenDeps); | ||||
MDC.ScanInstance.getASTReader()->visitTopLevelModuleMaps( | for (const auto &E : MDC.ScanInstance.SortedFiles[M->getFullModuleName()]) { | ||||
*MF, [&](const FileEntry *FE) { | if (!E.IsTopLevelModuleMap) | ||||
if (FE->getName().endswith("__inferred_module.map")) | continue; | ||||
return; | if (E.FE->getName().endswith("__inferred_module.map")) | ||||
MD.ModuleMapFileDeps.emplace_back(FE->getName()); | continue; | ||||
}); | MD.ModuleMapFileDeps.emplace_back(E.FE->getName()); | ||||
} | |||||
CompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs( | CompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs( | ||||
MD, [&](CompilerInvocation &BuildInvocation) { | MD, [&](CompilerInvocation &BuildInvocation) { | ||||
if (MDC.OptimizeArgs) | if (MDC.OptimizeArgs) | ||||
optimizeHeaderSearchOpts(BuildInvocation.getHeaderSearchOpts(), | optimizeHeaderSearchOpts(BuildInvocation.getHeaderSearchOpts(), M, | ||||
*MDC.ScanInstance.getASTReader(), *MF); | MDC.ScanInstance); | ||||
}); | }); | ||||
MDC.associateWithContextHash(CI, MD); | MDC.associateWithContextHash(CI, MD); | ||||
// Finish the compiler invocation. Requires dependencies and the context hash. | // Finish the compiler invocation. Requires dependencies and the context hash. | ||||
MDC.addOutputPaths(CI, MD); | MDC.addOutputPaths(CI, MD); | ||||
MD.BuildArguments = CI.getCC1CommandLine(); | MD.BuildArguments = CI.getCC1CommandLine(); | ||||
▲ Show 20 Lines • Show All 131 Lines • Show Last 20 Lines |