|
12 | 12 | #include "clang/Frontend/CompilerInstance.h"
|
13 | 13 | #include "clang/Lex/Preprocessor.h"
|
14 | 14 | #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
|
| 15 | +#include "llvm/Support/StringSaver.h" |
15 | 16 |
|
16 | 17 | using namespace clang;
|
17 | 18 | using namespace tooling;
|
18 | 19 | using namespace dependencies;
|
19 | 20 |
|
| 21 | +static CompilerInvocation |
| 22 | +makeInvocationForModuleBuildWithoutPaths(const ModuleDeps &Deps) { |
| 23 | + // Make a deep copy of the invocation. |
| 24 | + CompilerInvocation CI(*Deps.Invocation); |
| 25 | + |
| 26 | + // Remove options incompatible with explicit module build. |
| 27 | + CI.getFrontendOpts().Inputs.clear(); |
| 28 | + CI.getFrontendOpts().OutputFile.clear(); |
| 29 | + |
| 30 | + CI.getFrontendOpts().ProgramAction = frontend::GenerateModule; |
| 31 | + CI.getLangOpts()->ModuleName = Deps.ID.ModuleName; |
| 32 | + CI.getFrontendOpts().IsSystemModule = Deps.IsSystem; |
| 33 | + |
| 34 | + CI.getLangOpts()->ImplicitModules = false; |
| 35 | + CI.getHeaderSearchOpts().ImplicitModuleMaps = false; |
| 36 | + |
| 37 | + return CI; |
| 38 | +} |
| 39 | + |
| 40 | +static std::vector<std::string> |
| 41 | +serializeCompilerInvocation(CompilerInvocation &CI) { |
| 42 | + // Set up string allocator. |
| 43 | + llvm::BumpPtrAllocator Alloc; |
| 44 | + llvm::StringSaver Strings(Alloc); |
| 45 | + auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); }; |
| 46 | + SmallVector<const char *, 32> Args; |
| 47 | + |
| 48 | + // Synthesize full command line from the CompilerInvocation. |
| 49 | + CI.generateCC1CommandLine(Args, SA); |
| 50 | + |
| 51 | + // Convert arguments to the return type. |
| 52 | + std::vector<std::string> Ret; |
| 53 | + Ret.reserve(Args.size()); |
| 54 | + for (const char *Arg : Args) |
| 55 | + Ret.emplace_back(Arg); |
| 56 | + |
| 57 | + return Ret; |
| 58 | +} |
| 59 | + |
20 | 60 | std::vector<std::string> ModuleDeps::getFullCommandLine(
|
21 | 61 | std::function<StringRef(ModuleID)> LookupPCMPath,
|
22 | 62 | std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
|
23 |
| - // TODO: Build full command line. That also means capturing the original |
24 |
| - // command line into NonPathCommandLine. |
25 |
| - |
26 |
| - std::vector<std::string> Ret{ |
27 |
| - "-fno-implicit-modules", |
28 |
| - "-fno-implicit-module-maps", |
29 |
| - }; |
| 63 | + CompilerInvocation CI(makeInvocationForModuleBuildWithoutPaths(*this)); |
30 | 64 |
|
31 |
| - std::vector<std::string> PCMPaths; |
32 |
| - std::vector<std::string> ModMapPaths; |
33 | 65 | dependencies::detail::collectPCMAndModuleMapPaths(
|
34 |
| - ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths); |
35 |
| - for (const std::string &PCMPath : PCMPaths) |
36 |
| - Ret.push_back("-fmodule-file=" + PCMPath); |
37 |
| - for (const std::string &ModMapPath : ModMapPaths) |
38 |
| - Ret.push_back("-fmodule-map-file=" + ModMapPath); |
| 66 | + ClangModuleDeps, LookupPCMPath, LookupModuleDeps, |
| 67 | + CI.getFrontendOpts().ModuleFiles, CI.getFrontendOpts().ModuleMapFiles); |
39 | 68 |
|
40 |
| - return Ret; |
| 69 | + return serializeCompilerInvocation(CI); |
41 | 70 | }
|
42 | 71 |
|
43 | 72 | void dependencies::detail::collectPCMAndModuleMapPaths(
|
@@ -149,10 +178,12 @@ void ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
|
149 | 178 | .getModuleMap()
|
150 | 179 | .getContainingModuleMapFile(M);
|
151 | 180 |
|
| 181 | + MD.Invocation = Instance.getInvocationPtr(); |
152 | 182 | MD.ClangModuleMapFile = std::string(ModuleMap ? ModuleMap->getName() : "");
|
153 | 183 | MD.ID.ModuleName = M->getFullModuleName();
|
154 | 184 | MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
|
155 | 185 | MD.ID.ContextHash = MDC.ContextHash;
|
| 186 | + MD.IsSystem = M->IsSystem; |
156 | 187 | serialization::ModuleFile *MF =
|
157 | 188 | MDC.Instance.getASTReader()->getModuleManager().lookup(M->getASTFile());
|
158 | 189 | MDC.Instance.getASTReader()->visitInputFiles(
|
|
0 commit comments