15#include "llvm/ADT/STLExtras.h"
16#include "llvm/Support/BLAKE3.h"
17#include "llvm/Support/StringSaver.h"
21using namespace tooling;
22using namespace dependencies;
27 for (StringRef FileDep : FileDeps) {
28 auto ResolvedFileDep =
35 assert(!std::holds_alternative<std::monostate>(BuildInfo) &&
36 "Using uninitialized ModuleDeps");
37 if (
const auto *CI = std::get_if<CowCompilerInvocation>(&BuildInfo))
38 BuildInfo = CI->getCC1CommandLine();
39 return std::get<std::vector<std::string>>(BuildInfo);
49 std::vector<HeaderSearchOptions::Entry> Entries;
52 llvm::BitVector SearchPathUsage(Entries.size());
53 llvm::DenseSet<const serialization::ModuleFile *>
Visited;
64 if (SearchPathUsage.size() != Entries.size())
65 llvm::report_fatal_error(
66 "Inconsistent search path options between modules detected");
68 for (
auto Idx : SearchPathUsage.set_bits())
69 Opts.
UserEntries.push_back(std::move(Entries[Idx]));
72 std::vector<std::string> VFSOverlayFiles;
75 llvm::BitVector VFSUsage(VFSOverlayFiles.size());
76 llvm::DenseSet<const serialization::ModuleFile *>
Visited;
90 auto VFSMap = PrebuiltModuleVFSMap.find(MF->
FileName);
91 if (VFSMap == PrebuiltModuleVFSMap.end())
93 for (std::size_t I = 0,
E = VFSOverlayFiles.size(); I !=
E; ++I) {
94 if (VFSMap->second.contains(VFSOverlayFiles[I]))
101 if (VFSUsage.size() != VFSOverlayFiles.size())
102 llvm::report_fatal_error(
103 "Inconsistent -ivfsoverlay options between modules detected");
105 for (
auto Idx : VFSUsage.set_bits())
111 bool IsSystemModule) {
116 bool Wsystem_headers =
false;
117 for (StringRef Opt : Opts.
Warnings) {
118 bool isPositive = !Opt.consume_front(
"no-");
119 if (Opt ==
"system-headers")
120 Wsystem_headers = isPositive;
132static std::vector<std::string>
splitString(std::string S,
char Separator) {
134 StringRef(S).split(Segments, Separator, -1,
false);
135 std::vector<std::string>
Result;
136 Result.reserve(Segments.size());
137 for (StringRef Segment : Segments)
138 Result.push_back(Segment.str());
226 [&CI](
const std::pair<std::string, bool> &Def) {
227 StringRef MacroDef = Def.first;
228 return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
229 llvm::CachedHashString(MacroDef.split(
'=').first));
239ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
253 auto CurrentModuleMapEntry =
255 assert(CurrentModuleMapEntry &&
"module map file entry not found");
264 auto ModuleMapEntry =
266 assert(ModuleMapEntry &&
"module map file entry not found");
273 if (EagerLoadModules && DepModuleMapFiles.contains(*ModuleMapEntry))
278 if (*ModuleMapEntry == *CurrentModuleMapEntry &&
279 !DepModuleMapFiles.contains(*ModuleMapEntry))
306llvm::DenseSet<const FileEntry *> ModuleDepCollector::collectModuleMapFiles(
308 llvm::DenseSet<const FileEntry *> ModuleMapFiles;
309 for (
const ModuleID &MID : ClangModuleDeps) {
311 assert(MD &&
"Inconsistent dependency info");
315 assert(FE &&
"Missing module map file that was previously found");
316 ModuleMapFiles.insert(*FE);
318 return ModuleMapFiles;
321void ModuleDepCollector::addModuleMapFiles(
323 if (EagerLoadModules)
326 for (
const ModuleID &MID : ClangModuleDeps) {
328 assert(MD &&
"Inconsistent dependency info");
333void ModuleDepCollector::addModuleFiles(
335 for (
const ModuleID &MID : ClangModuleDeps) {
336 std::string PCMPath =
338 if (EagerLoadModules)
342 {MID.ModuleName, std::move(PCMPath)});
346void ModuleDepCollector::addModuleFiles(
348 for (
const ModuleID &MID : ClangModuleDeps) {
349 std::string PCMPath =
351 if (EagerLoadModules)
355 {MID.ModuleName, std::move(PCMPath)});
383 CurrentModuleMap->getNameAsRequested());
386 for (
const auto &KV : ModularDeps)
387 if (DirectModularDeps.contains(KV.first))
388 DirectDeps.push_back(KV.second->ID);
391 addModuleMapFiles(CI, DirectDeps);
393 addModuleFiles(CI, DirectDeps);
395 for (
const auto &KV : DirectPrebuiltModularDeps)
402 bool EagerLoadModules,
403 llvm::vfs::FileSystem &
VFS) {
404 llvm::HashBuilder<llvm::TruncatedBLAKE3<16>, llvm::endianness::native>
412 llvm::ErrorOr<std::string> CWD =
VFS.getCurrentWorkingDirectory();
414 HashBuilder.add(*CWD);
418 ArgVec.reserve(4096);
420 Arg.toVector(ArgVec);
421 ArgVec.push_back(
'\0');
423 HashBuilder.add(ArgVec);
431 HashBuilder.add(ID.ModuleName);
432 HashBuilder.add(ID.ContextHash);
435 HashBuilder.add(EagerLoadModules);
437 llvm::BLAKE3Result<16> Hash = HashBuilder.final();
438 std::array<uint64_t, 2> Words;
439 static_assert(
sizeof(Hash) ==
sizeof(Words),
"Hash must match Words");
440 std::memcpy(Words.data(), Hash.data(),
sizeof(Hash));
441 return toString(llvm::APInt(
sizeof(Words) * 8, Words), 36,
false);
444void ModuleDepCollector::associateWithContextHash(
448 bool Inserted = ModuleDepsByID.insert({Deps.
ID, &Deps}).second;
450 assert(Inserted &&
"duplicate module mapping");
463 if (MDC.ContextHash.empty()) {
473 if (std::optional<StringRef>
Filename =
SM.getNonBuiltinFilenameForID(FID))
474 MDC.addFileDep(llvm::sys::path::remove_leading_dotslash(*
Filename));
480 StringRef SearchPath, StringRef RelativePath,
const Module *SuggestedModule,
482 if (!
File && !ModuleImported) {
487 handleImport(SuggestedModule);
497 MDC.RequiredStdCXXModules.push_back(RequiredModule);
501 handleImport(Imported);
504void ModuleDepCollectorPP::handleImport(
const Module *Imported) {
510 if (MDC.isPrebuiltModule(TopLevelModule))
511 MDC.DirectPrebuiltModularDeps.insert(
514 MDC.DirectModularDeps.insert(TopLevelModule);
524 if (PP.isInNamedModule()) {
526 ProvidedModule.
ModuleName = PP.getNamedModuleName();
532 if (PP.isInImplementationUnit())
533 MDC.RequiredStdCXXModules.push_back(ProvidedModule);
535 MDC.ProvidedStdCXXModule = ProvidedModule;
543 if (!MDC.isPrebuiltModule(M))
544 MDC.DirectModularDeps.insert(M);
546 for (
const Module *M : MDC.DirectModularDeps)
547 handleTopLevelModule(M);
551 if (MDC.IsStdModuleP1689Format)
553 MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules);
555 for (
auto &&I : MDC.ModularDeps)
558 for (
const Module *M : MDC.DirectModularDeps) {
559 auto It = MDC.ModularDeps.find(M);
561 if (It != MDC.ModularDeps.end())
565 for (
auto &&I : MDC.FileDeps)
568 for (
auto &&I : MDC.DirectPrebuiltModularDeps)
572std::optional<ModuleID>
573ModuleDepCollectorPP::handleTopLevelModule(
const Module *M) {