forked from OSchip/llvm-project
[clang][deps] Generate the full command-line for modules
This patch uses the new `CompilerInvocation::generateCC1CommandLine` to generate the full canonical command line for modular dependencies, instead of only appending additional arguments. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D100534
This commit is contained in:
parent
cf2fc41bd1
commit
0a92e09c07
|
@ -225,9 +225,11 @@ public:
|
|||
|
||||
bool hasInvocation() const { return Invocation != nullptr; }
|
||||
|
||||
CompilerInvocation &getInvocation() {
|
||||
CompilerInvocation &getInvocation() { return *getInvocationPtr(); }
|
||||
|
||||
std::shared_ptr<CompilerInvocation> getInvocationPtr() {
|
||||
assert(Invocation && "Compiler instance has no invocation!");
|
||||
return *Invocation;
|
||||
return Invocation;
|
||||
}
|
||||
|
||||
/// setInvocation - Replace the current invocation.
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/Utils.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
@ -47,6 +48,9 @@ struct ModuleDeps {
|
|||
/// The identifier of the module.
|
||||
ModuleID ID;
|
||||
|
||||
/// Whether this is a "system" module.
|
||||
bool IsSystem;
|
||||
|
||||
/// The path to the modulemap file which defines this module.
|
||||
///
|
||||
/// This can be used to explicitly build this module. This file will
|
||||
|
@ -71,6 +75,10 @@ struct ModuleDeps {
|
|||
// the primary TU.
|
||||
bool ImportedByMainFile = false;
|
||||
|
||||
/// The compiler invocation associated with the translation unit that imports
|
||||
/// this module.
|
||||
std::shared_ptr<CompilerInvocation> Invocation;
|
||||
|
||||
/// Gets the full command line suitable for passing to clang.
|
||||
///
|
||||
/// \param LookupPCMPath This function is called to fill in `-fmodule-file=`
|
||||
|
|
|
@ -12,32 +12,61 @@
|
|||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace tooling;
|
||||
using namespace dependencies;
|
||||
|
||||
static CompilerInvocation
|
||||
makeInvocationForModuleBuildWithoutPaths(const ModuleDeps &Deps) {
|
||||
// Make a deep copy of the invocation.
|
||||
CompilerInvocation CI(*Deps.Invocation);
|
||||
|
||||
// Remove options incompatible with explicit module build.
|
||||
CI.getFrontendOpts().Inputs.clear();
|
||||
CI.getFrontendOpts().OutputFile.clear();
|
||||
|
||||
CI.getFrontendOpts().ProgramAction = frontend::GenerateModule;
|
||||
CI.getLangOpts()->ModuleName = Deps.ID.ModuleName;
|
||||
CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
|
||||
|
||||
CI.getLangOpts()->ImplicitModules = false;
|
||||
CI.getHeaderSearchOpts().ImplicitModuleMaps = false;
|
||||
|
||||
return CI;
|
||||
}
|
||||
|
||||
static std::vector<std::string>
|
||||
serializeCompilerInvocation(CompilerInvocation &CI) {
|
||||
// Set up string allocator.
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
llvm::StringSaver Strings(Alloc);
|
||||
auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); };
|
||||
SmallVector<const char *, 32> Args;
|
||||
|
||||
// Synthesize full command line from the CompilerInvocation.
|
||||
CI.generateCC1CommandLine(Args, SA);
|
||||
|
||||
// Convert arguments to the return type.
|
||||
std::vector<std::string> Ret;
|
||||
Ret.reserve(Args.size());
|
||||
for (const char *Arg : Args)
|
||||
Ret.emplace_back(Arg);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> ModuleDeps::getFullCommandLine(
|
||||
std::function<StringRef(ModuleID)> LookupPCMPath,
|
||||
std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
|
||||
// TODO: Build full command line. That also means capturing the original
|
||||
// command line into NonPathCommandLine.
|
||||
CompilerInvocation CI(makeInvocationForModuleBuildWithoutPaths(*this));
|
||||
|
||||
std::vector<std::string> Ret{
|
||||
"-fno-implicit-modules",
|
||||
"-fno-implicit-module-maps",
|
||||
};
|
||||
|
||||
std::vector<std::string> PCMPaths;
|
||||
std::vector<std::string> ModMapPaths;
|
||||
dependencies::detail::collectPCMAndModuleMapPaths(
|
||||
ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths);
|
||||
for (const std::string &PCMPath : PCMPaths)
|
||||
Ret.push_back("-fmodule-file=" + PCMPath);
|
||||
for (const std::string &ModMapPath : ModMapPaths)
|
||||
Ret.push_back("-fmodule-map-file=" + ModMapPath);
|
||||
ClangModuleDeps, LookupPCMPath, LookupModuleDeps,
|
||||
CI.getFrontendOpts().ModuleFiles, CI.getFrontendOpts().ModuleMapFiles);
|
||||
|
||||
return Ret;
|
||||
return serializeCompilerInvocation(CI);
|
||||
}
|
||||
|
||||
void dependencies::detail::collectPCMAndModuleMapPaths(
|
||||
|
@ -149,10 +178,12 @@ void ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
|
|||
.getModuleMap()
|
||||
.getContainingModuleMapFile(M);
|
||||
|
||||
MD.Invocation = Instance.getInvocationPtr();
|
||||
MD.ClangModuleMapFile = std::string(ModuleMap ? ModuleMap->getName() : "");
|
||||
MD.ID.ModuleName = M->getFullModuleName();
|
||||
MD.ImplicitModulePCMPath = std::string(M->getASTFile()->getName());
|
||||
MD.ID.ContextHash = MDC.ContextHash;
|
||||
MD.IsSystem = M->IsSystem;
|
||||
serialization::ModuleFile *MF =
|
||||
MDC.Instance.getASTReader()->getModuleManager().lookup(M->getASTFile());
|
||||
MDC.Instance.getASTReader()->visitInputFiles(
|
||||
|
|
|
@ -37,11 +37,11 @@
|
|||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
|
||||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-fno-implicit-modules",
|
||||
// CHECK-NEXT: "-fno-implicit-module-maps",
|
||||
// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[CONTEXT_HASH_H1]]/header2-{{[A-Z0-9]+}}.pcm",
|
||||
// CHECK-NEXT: "-fmodule-map-file=[[PREFIX]]/Inputs/module.modulemap"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK: "-fmodule-map-file=[[PREFIX]]/Inputs/module.modulemap",
|
||||
// CHECK: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[CONTEXT_HASH_H1]]/header2-{{[A-Z0-9]+}}.pcm",
|
||||
// CHECK-NOT: "-fimplicit-module-maps",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1]]",
|
||||
// CHECK-NEXT: "file-deps": [
|
||||
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
|
||||
|
@ -53,9 +53,9 @@
|
|||
// CHECK-NEXT: "clang-module-deps": [],
|
||||
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
|
||||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-fno-implicit-modules",
|
||||
// CHECK-NEXT: "-fno-implicit-module-maps"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NOT: "-fimplicit-module-maps",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H2:[A-Z0-9]+]]",
|
||||
// CHECK-NEXT: "file-deps": [
|
||||
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h",
|
||||
|
@ -67,9 +67,9 @@
|
|||
// CHECK-NEXT: "clang-module-deps": [],
|
||||
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/Inputs/module.modulemap",
|
||||
// CHECK-NEXT: "command-line": [
|
||||
// CHECK-NEXT: "-fno-implicit-modules",
|
||||
// CHECK-NEXT: "-fno-implicit-module-maps"
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NOT: "-fimplicit-module-maps",
|
||||
// CHECK: "-fno-implicit-modules",
|
||||
// CHECK: ],
|
||||
// CHECK-NEXT: "context-hash": "[[CONTEXT_HASH_H1]]",
|
||||
// CHECK-NEXT: "file-deps": [
|
||||
// CHECK-NEXT: "[[PREFIX]]/Inputs/header2.h",
|
||||
|
|
Loading…
Reference in New Issue