[clang] 83902c4 - Reapply "[clang][deps] Split translation units into individual -cc1 or other commands"
Ben Langmuir via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 31 09:45:41 PDT 2022
Author: Ben Langmuir
Date: 2022-08-31T09:45:11-07:00
New Revision: 83902c403611af3a52453867cb8848fb3fd6a39c
URL: https://github.com/llvm/llvm-project/commit/83902c403611af3a52453867cb8848fb3fd6a39c
DIFF: https://github.com/llvm/llvm-project/commit/83902c403611af3a52453867cb8848fb3fd6a39c.diff
LOG: Reapply "[clang][deps] Split translation units into individual -cc1 or other commands"
Attempt to fix the test failures observed in CI:
* Add Option dependency, which caused BUILD_SHARED_LIBS builds to fail
* Adapt tests that accidentally depended on the host platform: platforms
that don't use an integrated assembler (e.g. AIX) get a different set
of commands from the driver. Most dependency scanner tests can use
-fsyntax-only or -E instead of -c to avoid this, and in the rare case
we want to check -c specifically, set an explicit target so the
behaviour is independent of the host.
Original commit message follows.
---
Instead of trying to "fix" the original driver invocation by appending
arguments to it, split it into multiple commands, and for each -cc1
command use a CompilerInvocation to give precise control over the
invocation.
This change should make it easier to (in the future) canonicalize the
command-line (e.g. to improve hits in something like ccache), apply
optimizations, or start supporting multi-arch builds, which would
require different modules for each arch.
In the long run it may make sense to treat the TU commands as a
dependency graph, each with their own dependencies on modules or earlier
TU commands, but for now they are simply a list that is executed in
order, and the dependencies are simply duplicated. Since we currently
only support single-arch builds, there is no parallelism available in
the execution.
Differential Revision: https://reviews.llvm.org/D132405
Added:
clang/test/ClangScanDeps/deprecated-driver-api.c
clang/test/ClangScanDeps/multiple-commands.c
Modified:
clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
clang/lib/Tooling/DependencyScanning/CMakeLists.txt
clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
clang/test/ClangScanDeps/diagnostics.c
clang/test/ClangScanDeps/header-search-pruning-transitive.c
clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
clang/test/ClangScanDeps/modules-context-hash-outputs.c
clang/test/ClangScanDeps/modules-context-hash-warnings.c
clang/test/ClangScanDeps/modules-context-hash.c
clang/test/ClangScanDeps/modules-dep-args.c
clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
clang/test/ClangScanDeps/modules-full.cpp
clang/test/ClangScanDeps/modules-implicit-dot-private.m
clang/test/ClangScanDeps/modules-incomplete-umbrella.c
clang/test/ClangScanDeps/modules-inferred.m
clang/test/ClangScanDeps/modules-no-undeclared-includes.c
clang/test/ClangScanDeps/modules-pch-common-submodule.c
clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
clang/test/ClangScanDeps/modules-pch.c
clang/test/ClangScanDeps/removed-args.c
clang/tools/clang-scan-deps/ClangScanDeps.cpp
clang/utils/module-deps-to-rsp.py
Removed:
################################################################################
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index cc3f330828a39..c0d273297f18f 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -49,8 +49,16 @@ struct FullDependencies {
/// determined that the
diff erences are benign for this compilation.
std::vector<ModuleID> ClangModuleDeps;
- /// The command line of the TU (excluding the compiler executable).
- std::vector<std::string> CommandLine;
+ /// The sequence of commands required to build the translation unit. Commands
+ /// should be executed in order.
+ ///
+ /// FIXME: If we add support for multi-arch builds in clang-scan-deps, we
+ /// should make the dependencies between commands explicit to enable parallel
+ /// builds of each architecture.
+ std::vector<Command> Commands;
+
+ /// Deprecated driver command-line. This will be removed in a future version.
+ std::vector<std::string> DriverCommandLine;
};
struct FullDependenciesResult {
@@ -99,6 +107,12 @@ class DependencyScanningTool {
LookupModuleOutputCallback LookupModuleOutput,
llvm::Optional<StringRef> ModuleName = None);
+ llvm::Expected<FullDependenciesResult> getFullDependenciesLegacyDriverCommand(
+ const std::vector<std::string> &CommandLine, StringRef CWD,
+ const llvm::StringSet<> &AlreadySeen,
+ LookupModuleOutputCallback LookupModuleOutput,
+ llvm::Optional<StringRef> ModuleName = None);
+
private:
DependencyScanningWorker Worker;
};
@@ -111,6 +125,10 @@ class FullDependencyConsumer : public DependencyConsumer {
: AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput),
EagerLoadModules(EagerLoadModules) {}
+ void handleBuildCommand(Command Cmd) override {
+ Commands.push_back(std::move(Cmd));
+ }
+
void handleDependencyOutputOpts(const DependencyOutputOptions &) override {}
void handleFileDependency(StringRef File) override {
@@ -134,14 +152,17 @@ class FullDependencyConsumer : public DependencyConsumer {
return LookupModuleOutput(ID, Kind);
}
- FullDependenciesResult getFullDependencies(
+ FullDependenciesResult getFullDependenciesLegacyDriverCommand(
const std::vector<std::string> &OriginalCommandLine) const;
+ FullDependenciesResult takeFullDependencies();
+
private:
std::vector<std::string> Dependencies;
std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
llvm::MapVector<std::string, ModuleDeps, llvm::StringMap<unsigned>>
ClangModuleDeps;
+ std::vector<Command> Commands;
std::string ContextHash;
std::vector<std::string> OutputPaths;
const llvm::StringSet<> &AlreadySeen;
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
index b7015ca0ca43c..221906f9f9382 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
@@ -28,10 +28,20 @@ namespace dependencies {
class DependencyScanningWorkerFilesystem;
+/// A command-line tool invocation that is part of building a TU.
+///
+/// \see FullDependencies::Commands.
+struct Command {
+ std::string Executable;
+ std::vector<std::string> Arguments;
+};
+
class DependencyConsumer {
public:
virtual ~DependencyConsumer() {}
+ virtual void handleBuildCommand(Command Cmd) = 0;
+
virtual void
handleDependencyOutputOpts(const DependencyOutputOptions &Opts) = 0;
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index c0b7b2b57b583..c9fa763cad29c 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -181,12 +181,16 @@ class ModuleDepCollector final : public DependencyCollector {
public:
ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
CompilerInstance &ScanInstance, DependencyConsumer &C,
- CompilerInvocation &&OriginalCI, bool OptimizeArgs,
+ CompilerInvocation OriginalCI, bool OptimizeArgs,
bool EagerLoadModules);
void attachToPreprocessor(Preprocessor &PP) override;
void attachToASTReader(ASTReader &R) override;
+ /// Apply any changes implied by the discovered dependencies to the given
+ /// invocation, (e.g. disable implicit modules, add explicit module paths).
+ void applyDiscoveredDependencies(CompilerInvocation &CI);
+
private:
friend ModuleDepCollectorPP;
diff --git a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
index ce455e518070b..88d4a057a84a0 100644
--- a/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
+++ b/clang/lib/Tooling/DependencyScanning/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
Core
+ Option
Support
)
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
index 7c15ead465c5e..88540dd242cb4 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -45,6 +45,8 @@ llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
/// Prints out all of the gathered dependencies into a string.
class MakeDependencyPrinterConsumer : public DependencyConsumer {
public:
+ void handleBuildCommand(Command) override {}
+
void
handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
@@ -120,14 +122,53 @@ DependencyScanningTool::getFullDependencies(
Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
if (Result)
return std::move(Result);
- return Consumer.getFullDependencies(CommandLine);
+ return Consumer.takeFullDependencies();
+}
+
+llvm::Expected<FullDependenciesResult>
+DependencyScanningTool::getFullDependenciesLegacyDriverCommand(
+ const std::vector<std::string> &CommandLine, StringRef CWD,
+ const llvm::StringSet<> &AlreadySeen,
+ LookupModuleOutputCallback LookupModuleOutput,
+ llvm::Optional<StringRef> ModuleName) {
+ FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput,
+ Worker.shouldEagerLoadModules());
+ llvm::Error Result =
+ Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
+ if (Result)
+ return std::move(Result);
+ return Consumer.getFullDependenciesLegacyDriverCommand(CommandLine);
+}
+
+FullDependenciesResult FullDependencyConsumer::takeFullDependencies() {
+ FullDependenciesResult FDR;
+ FullDependencies &FD = FDR.FullDeps;
+
+ FD.ID.ContextHash = std::move(ContextHash);
+ FD.FileDeps = std::move(Dependencies);
+ FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
+ FD.Commands = std::move(Commands);
+
+ for (auto &&M : ClangModuleDeps) {
+ auto &MD = M.second;
+ if (MD.ImportedByMainFile)
+ FD.ClangModuleDeps.push_back(MD.ID);
+ // TODO: Avoid handleModuleDependency even being called for modules
+ // we've already seen.
+ if (AlreadySeen.count(M.first))
+ continue;
+ FDR.DiscoveredModules.push_back(std::move(MD));
+ }
+
+ return FDR;
}
-FullDependenciesResult FullDependencyConsumer::getFullDependencies(
+FullDependenciesResult
+FullDependencyConsumer::getFullDependenciesLegacyDriverCommand(
const std::vector<std::string> &OriginalCommandLine) const {
FullDependencies FD;
- FD.CommandLine = makeTUCommandLineWithoutPaths(
+ FD.DriverCommandLine = makeTUCommandLineWithoutPaths(
ArrayRef<std::string>(OriginalCommandLine).slice(1));
FD.ID.ContextHash = std::move(ContextHash);
@@ -135,7 +176,7 @@ FullDependenciesResult FullDependencyConsumer::getFullDependencies(
FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps)
- FD.CommandLine.push_back("-fmodule-file=" + PMD.PCMFile);
+ FD.DriverCommandLine.push_back("-fmodule-file=" + PMD.PCMFile);
for (auto &&M : ClangModuleDeps) {
auto &MD = M.second;
@@ -143,11 +184,12 @@ FullDependenciesResult FullDependencyConsumer::getFullDependencies(
FD.ClangModuleDeps.push_back(MD.ID);
auto PCMPath = LookupModuleOutput(MD.ID, ModuleOutputKind::ModuleFile);
if (EagerLoadModules) {
- FD.CommandLine.push_back("-fmodule-file=" + PCMPath);
+ FD.DriverCommandLine.push_back("-fmodule-file=" + PCMPath);
} else {
- FD.CommandLine.push_back("-fmodule-map-file=" + MD.ClangModuleMapFile);
- FD.CommandLine.push_back("-fmodule-file=" + MD.ID.ModuleName + "=" +
- PCMPath);
+ FD.DriverCommandLine.push_back("-fmodule-map-file=" +
+ MD.ClangModuleMapFile);
+ FD.DriverCommandLine.push_back("-fmodule-file=" + MD.ID.ModuleName +
+ "=" + PCMPath);
}
}
}
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
index b179cf0e6b0ef..3968656f4632b 100644
--- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
+++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
@@ -7,7 +7,12 @@
//===----------------------------------------------------------------------===//
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/Job.h"
+#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
@@ -17,6 +22,7 @@
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Host.h"
using namespace clang;
using namespace tooling;
@@ -156,6 +162,17 @@ class DependencyScanningAction : public tooling::ToolAction {
// Restore the value of DisableFree, which may be modified by Tooling.
OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
+ if (Scanned) {
+ // Scanning runs once for the first -cc1 invocation in a chain of driver
+ // jobs. For any dependent jobs, reuse the scanning result and just
+ // update the LastCC1Arguments to correspond to the new invocation.
+ // FIXME: to support multi-arch builds, each arch requires a separate scan
+ setLastCC1Arguments(std::move(OriginalInvocation));
+ return true;
+ }
+
+ Scanned = true;
+
// Create a compiler instance to handle the actual work.
CompilerInstance ScanInstance(std::move(PCHContainerOps));
ScanInstance.setInvocation(std::move(Invocation));
@@ -230,9 +247,10 @@ class DependencyScanningAction : public tooling::ToolAction {
std::move(Opts), WorkingDirectory, Consumer));
break;
case ScanningOutputFormat::Full:
- ScanInstance.addDependencyCollector(std::make_shared<ModuleDepCollector>(
- std::move(Opts), ScanInstance, Consumer,
- std::move(OriginalInvocation), OptimizeArgs, EagerLoadModules));
+ MDC = std::make_shared<ModuleDepCollector>(
+ std::move(Opts), ScanInstance, Consumer, OriginalInvocation,
+ OptimizeArgs, EagerLoadModules);
+ ScanInstance.addDependencyCollector(MDC);
break;
}
@@ -253,9 +271,31 @@ class DependencyScanningAction : public tooling::ToolAction {
const bool Result = ScanInstance.ExecuteAction(*Action);
if (!DepFS)
FileMgr->clearStatCache();
+
+ if (Result)
+ setLastCC1Arguments(std::move(OriginalInvocation));
+
+ return Result;
+ }
+
+ bool hasScanned() const { return Scanned; }
+
+ /// Take the cc1 arguments corresponding to the most recent invocation used
+ /// with this action. Any modifications implied by the discovered dependencies
+ /// will have already been applied.
+ std::vector<std::string> takeLastCC1Arguments() {
+ std::vector<std::string> Result;
+ std::swap(Result, LastCC1Arguments); // Reset LastCC1Arguments to empty.
return Result;
}
+private:
+ void setLastCC1Arguments(CompilerInvocation &&CI) {
+ if (MDC)
+ MDC->applyDiscoveredDependencies(CI);
+ LastCC1Arguments = CI.getCC1CommandLine();
+ }
+
private:
StringRef WorkingDirectory;
DependencyConsumer &Consumer;
@@ -265,6 +305,9 @@ class DependencyScanningAction : public tooling::ToolAction {
bool EagerLoadModules;
bool DisableFree;
llvm::Optional<StringRef> ModuleName;
+ std::shared_ptr<ModuleDepCollector> MDC;
+ std::vector<std::string> LastCC1Arguments;
+ bool Scanned = false;
};
} // end anonymous namespace
@@ -313,6 +356,36 @@ runWithDiags(DiagnosticOptions *DiagOpts,
llvm::inconvertibleErrorCode());
}
+static bool forEachDriverJob(
+ ArrayRef<std::string> Args, DiagnosticsEngine &Diags, FileManager &FM,
+ llvm::function_ref<bool(const driver::Command &Cmd)> Callback) {
+ std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
+ Args[0], llvm::sys::getDefaultTargetTriple(), Diags,
+ "clang LLVM compiler", &FM.getVirtualFileSystem());
+ Driver->setTitle("clang_based_tool");
+
+ std::vector<const char *> Argv;
+ for (const std::string &Arg : Args)
+ Argv.push_back(Arg.c_str());
+
+ // The "input file not found" diagnostics from the driver are useful.
+ // The driver is only aware of the VFS working directory, but some clients
+ // change this at the FileManager level instead.
+ // In this case the checks have false positives, so skip them.
+ if (!FM.getFileSystemOpts().WorkingDir.empty())
+ Driver->setCheckInputsExist(false);
+ const std::unique_ptr<driver::Compilation> Compilation(
+ Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
+ if (!Compilation)
+ return false;
+
+ for (const driver::Command &Job : Compilation->getJobs()) {
+ if (!Callback(Job))
+ return false;
+ }
+ return true;
+}
+
llvm::Error DependencyScanningWorker::computeDependencies(
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
DependencyConsumer &Consumer, llvm::Optional<StringRef> ModuleName) {
@@ -338,25 +411,60 @@ llvm::Error DependencyScanningWorker::computeDependencies(
llvm::transform(CommandLine, FinalCCommandLine.begin(),
[](const std::string &Str) { return Str.c_str(); });
- return runWithDiags(CreateAndPopulateDiagOpts(FinalCCommandLine).release(),
- [&](DiagnosticConsumer &DC, DiagnosticOptions &DiagOpts) {
- // DisableFree is modified by Tooling for running
- // in-process; preserve the original value, which is
- // always true for a driver invocation.
- bool DisableFree = true;
- DependencyScanningAction Action(
- WorkingDirectory, Consumer, DepFS, Format,
- OptimizeArgs, EagerLoadModules, DisableFree,
- ModuleName);
- // Create an invocation that uses the underlying file
- // system to ensure that any file system requests that
- // are made by the driver do not go through the
- // dependency scanning filesystem.
- ToolInvocation Invocation(FinalCommandLine, &Action,
- CurrentFiles.get(),
- PCHContainerOps);
- Invocation.setDiagnosticConsumer(&DC);
- Invocation.setDiagnosticOptions(&DiagOpts);
- return Invocation.run();
- });
+ return runWithDiags(
+ CreateAndPopulateDiagOpts(FinalCCommandLine).release(),
+ [&](DiagnosticConsumer &DC, DiagnosticOptions &DiagOpts) {
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
+ CompilerInstance::createDiagnostics(&DiagOpts, &DC, false);
+ // Although `Diagnostics` are used only for command-line parsing, the
+ // custom `DiagConsumer` might expect a `SourceManager` to be present.
+ SourceManager SrcMgr(*Diags, *CurrentFiles);
+ Diags->setSourceManager(&SrcMgr);
+ // DisableFree is modified by Tooling for running
+ // in-process; preserve the original value, which is
+ // always true for a driver invocation.
+ bool DisableFree = true;
+ DependencyScanningAction Action(WorkingDirectory, Consumer, DepFS,
+ Format, OptimizeArgs, EagerLoadModules,
+ DisableFree, ModuleName);
+ bool Success = forEachDriverJob(
+ FinalCommandLine, *Diags, *CurrentFiles,
+ [&](const driver::Command &Cmd) {
+ if (StringRef(Cmd.getCreator().getName()) != "clang") {
+ // Non-clang command. Just pass through to the dependency
+ // consumer.
+ Consumer.handleBuildCommand(
+ {Cmd.getExecutable(),
+ {Cmd.getArguments().begin(), Cmd.getArguments().end()}});
+ return true;
+ }
+
+ std::vector<std::string> Argv;
+ Argv.push_back(Cmd.getExecutable());
+ Argv.insert(Argv.end(), Cmd.getArguments().begin(),
+ Cmd.getArguments().end());
+
+ // Create an invocation that uses the underlying file
+ // system to ensure that any file system requests that
+ // are made by the driver do not go through the
+ // dependency scanning filesystem.
+ ToolInvocation Invocation(std::move(Argv), &Action,
+ &*CurrentFiles, PCHContainerOps);
+ Invocation.setDiagnosticConsumer(Diags->getClient());
+ Invocation.setDiagnosticOptions(&Diags->getDiagnosticOptions());
+ if (!Invocation.run())
+ return false;
+
+ std::vector<std::string> Args = Action.takeLastCC1Arguments();
+ Consumer.handleBuildCommand(
+ {Cmd.getExecutable(), std::move(Args)});
+ return true;
+ });
+
+ if (Success && !Action.hasScanned()) {
+ Diags->Report(diag::err_fe_expected_compiler_job)
+ << llvm::join(FinalCommandLine, " ");
+ }
+ return Success && Action.hasScanned();
+ });
}
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 977ad23866ffc..bb6673d1373db 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -174,6 +174,34 @@ void ModuleDepCollector::addModuleFiles(
}
}
+static bool needsModules(FrontendInputFile FIF) {
+ switch (FIF.getKind().getLanguage()) {
+ case Language::Unknown:
+ case Language::Asm:
+ case Language::LLVM_IR:
+ return false;
+ default:
+ return true;
+ }
+}
+
+void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
+ CI.clearImplicitModuleBuildOptions();
+
+ if (llvm::any_of(CI.getFrontendOpts().Inputs, needsModules)) {
+ SmallVector<ModuleID> DirectDeps;
+ for (const auto &KV : ModularDeps)
+ if (KV.second->ImportedByMainFile)
+ DirectDeps.push_back(KV.second->ID);
+
+ addModuleMapFiles(CI, DirectDeps);
+ addModuleFiles(CI, DirectDeps);
+
+ for (const auto &KV : DirectPrebuiltModularDeps)
+ CI.getFrontendOpts().ModuleFiles.push_back(KV.second.PCMFile);
+ }
+}
+
static std::string getModuleContextHash(const ModuleDeps &MD,
const CompilerInvocation &CI,
bool EagerLoadModules) {
@@ -508,7 +536,7 @@ void ModuleDepCollectorPP::addAffectingModule(
ModuleDepCollector::ModuleDepCollector(
std::unique_ptr<DependencyOutputOptions> Opts,
CompilerInstance &ScanInstance, DependencyConsumer &C,
- CompilerInvocation &&OriginalCI, bool OptimizeArgs, bool EagerLoadModules)
+ CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules)
: ScanInstance(ScanInstance), Consumer(C), Opts(std::move(Opts)),
OriginalInvocation(std::move(OriginalCI)), OptimizeArgs(OptimizeArgs),
EagerLoadModules(EagerLoadModules) {}
diff --git a/clang/test/ClangScanDeps/deprecated-driver-api.c b/clang/test/ClangScanDeps/deprecated-driver-api.c
new file mode 100644
index 0000000000000..230673a5927ea
--- /dev/null
+++ b/clang/test/ClangScanDeps/deprecated-driver-api.c
@@ -0,0 +1,38 @@
+// Test the deprecated version of the API that returns a driver command instead
+// of multiple -cc1 commands.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json
+
+// RUN: clang-scan-deps -compilation-database=%t/cdb.json -format experimental-full \
+// RUN: -deprecated-driver-command | sed 's:\\\\\?:/:g' | FileCheck %s
+
+// CHECK: "command-line": [
+// CHECK: "-c"
+// CHECK: "{{.*}}tu.c"
+// CHECK: "-save-temps"
+// CHECK: "-fno-implicit-modules"
+// CHECK: "-fno-implicit-module-maps"
+// CHECK: ]
+// CHECK: "file-deps": [
+// CHECK: "{{.*}}tu.c",
+// CHECK: "{{.*}}header.h"
+// CHECK: ]
+
+//--- cdb.json.in
+[{
+ "directory": "DIR",
+ "command": "clang -c DIR/tu.c -save-temps",
+ "file": "DIR/tu.c"
+}]
+
+//--- header.h
+void bar(void);
+
+//--- tu.c
+#include "header.h"
+
+void foo(void) {
+ bar();
+}
diff --git a/clang/test/ClangScanDeps/diagnostics.c b/clang/test/ClangScanDeps/diagnostics.c
index bf42d3bf0e142..b5ca499192a2a 100644
--- a/clang/test/ClangScanDeps/diagnostics.c
+++ b/clang/test/ClangScanDeps/diagnostics.c
@@ -28,7 +28,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:.*]],
+// CHECK: "clang-context-hash": "[[HASH_TU:.*]],
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_MOD]]",
@@ -36,13 +36,11 @@
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
-// CHECK: "-fno-implicit-modules"
-// CHECK: "-fno-implicit-module-maps"
+// CHECK-NOT: "-fimplicit-modules"
+// CHECK-NOT: "-fimplicit-module-maps"
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/tu.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/header-search-pruning-transitive.c b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
index 5e6e02ba2143c..512bf5ec5cc6f 100644
--- a/clang/test/ClangScanDeps/header-search-pruning-transitive.c
+++ b/clang/test/ClangScanDeps/header-search-pruning-transitive.c
@@ -41,14 +41,14 @@ module X { header "X.h" }
[{
"file": "DIR/test.c",
"directory": "DIR",
- "command": "clang -c test.c -o DIR/test.o -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ia -Ib -Iend"
+ "command": "clang -fsyntax-only test.c -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ia -Ib -Iend"
}]
//--- cdb_without_a.json.template
[{
"file": "DIR/test.c",
"directory": "DIR",
- "command": "clang -c test.c -o DIR/test.o -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ib -Iend"
+ "command": "clang -fsyntax-only test.c -fmodules -fimplicit-modules -fmodules-cache-path=DIR/module-cache -fimplicit-module-maps -Ibegin -Ib -Iend"
}]
// RUN: sed -e "s|DIR|%/t|g" %t/cdb_with_a.json.template > %t/cdb_with_a.json
@@ -95,7 +95,7 @@ module X { header "X.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_X]]",
@@ -104,14 +104,13 @@ module X { header "X.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/test.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/test.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
-// CHECK-NEXT: {
+
+// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [
@@ -149,7 +148,7 @@ module X { header "X.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
@@ -158,10 +157,8 @@ module X { header "X.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/test.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/test.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c b/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
index 982bf1e06b519..9f7a62fb9eb74 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-ignore-macros.c
@@ -38,10 +38,11 @@
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-DFOO"
+// CHECK-NOT: "FOO"
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu1.c"
// CHECK-NEXT: }
-// CHECK-NEXT: {
+// CHECK: {
// CHECK: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_FOO]]"
@@ -49,11 +50,12 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
-// CHECK: "-DFOO"
+// CHECK: "-D"
+// CHECK-NEXT: "FOO"
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu2.c"
// CHECK-NEXT: }
-// CHECK-NEXT: {
+// CHECK: {
// CHECK: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_NO_FOO]]"
@@ -61,8 +63,9 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
-// CHECK: "-DFOO"
// CHECK: "-fmodules-ignore-macro=FOO"
+// CHECK: "-D"
+// CHECK-NEXT: "FOO"
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu3.c"
diff --git a/clang/test/ClangScanDeps/modules-context-hash-outputs.c b/clang/test/ClangScanDeps/modules-context-hash-outputs.c
index 041c7cd60fe4f..5e63e60a70370 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-outputs.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-outputs.c
@@ -35,11 +35,11 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
-// CHECK: "-MF"
+// CHECK: "-dependency-file"
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu1.c"
// CHECK-NEXT: }
-// CHECK-NEXT: {
+// CHECK: {
// CHECK: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH2]]"
@@ -48,6 +48,7 @@
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
// CHECK-NOT: "-MF"
+// CHECK-NOT: "-dependency-file"
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu2.c"
diff --git a/clang/test/ClangScanDeps/modules-context-hash-warnings.c b/clang/test/ClangScanDeps/modules-context-hash-warnings.c
index 8457c7db53fb0..09d2f20b329e3 100644
--- a/clang/test/ClangScanDeps/modules-context-hash-warnings.c
+++ b/clang/test/ClangScanDeps/modules-context-hash-warnings.c
@@ -39,7 +39,7 @@
// CHECK: ]
// CHECK: "input-file": "{{.*}}tu1.c"
// CHECK-NEXT: }
-// CHECK-NEXT: {
+// CHECK: {
// CHECK: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH2]]"
diff --git a/clang/test/ClangScanDeps/modules-context-hash.c b/clang/test/ClangScanDeps/modules-context-hash.c
index 2b285f8b14ce3..97a86534348f7 100644
--- a/clang/test/ClangScanDeps/modules-context-hash.c
+++ b/clang/test/ClangScanDeps/modules-context-hash.c
@@ -40,7 +40,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_MOD_A]]",
@@ -49,15 +49,13 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/tu.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
-// CHECK-NEXT: {
-// CHECK-NEXT: "modules": [
+
+// CHECK: "modules": [
// CHECK-NEXT: {
// CHECK-NEXT: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
@@ -79,7 +77,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NOT: "context-hash": "[[HASH_MOD_A]]",
@@ -88,10 +86,8 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/tu.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/modules-dep-args.c b/clang/test/ClangScanDeps/modules-dep-args.c
index ec2d994118493..12bdb6eb1f7fd 100644
--- a/clang/test/ClangScanDeps/modules-dep-args.c
+++ b/clang/test/ClangScanDeps/modules-dep-args.c
@@ -78,7 +78,7 @@ module Direct { header "direct.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
@@ -93,10 +93,8 @@ module Direct { header "direct.h" }
// CHECK_EAGER-NOT: "-fmodule-map-file={{.*}}"
// CHECK_EAGER: "-fmodule-file=[[PREFIX]]/{{.*}}/Direct-{{.*}}.pcm"
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/tu.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
\ No newline at end of file
diff --git a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
index a1afae195c297..a6206b1546751 100644
--- a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
+++ b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m
@@ -33,7 +33,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
+// CHECK: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_H2]]",
@@ -42,12 +42,10 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/modules-fmodule-name-no-module-built.m"
// CHECK-NEXT: "[[PREFIX]]/Inputs/header3.h"
// CHECK-NEXT: "[[PREFIX]]/Inputs/header.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/modules-fmodule-name-no-module-built.m"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp
index 38170ea81dde7..a19aafddcc140 100644
--- a/clang/test/ClangScanDeps/modules-full.cpp
+++ b/clang/test/ClangScanDeps/modules-full.cpp
@@ -82,76 +82,96 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: "commands": [
// CHECK-NEXT: {
-// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
-// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
+// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
+// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "command-line": [
+// CHECK-NOT: "-fimplicit-modules"
+// CHECK-NOT: "-fimplicit-module-maps"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
+// CHECK: ],
+// CHECK-NEXT: "executable": "{{.*}}clang{{.*}}"
+// CHECK-NEXT: "file-deps": [
+// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
// CHECK-NEXT: }
-// CHECK-NEXT: ],
-// CHECK-NEXT: "command-line": [
-// CHECK: "-fno-implicit-modules"
-// CHECK: "-fno-implicit-module-maps"
-// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
-// CHECK: ],
-// CHECK-NEXT: "file-deps": [
-// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
-// CHECK-NEXT: ],
-// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: "commands": [
// CHECK-NEXT: {
-// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
-// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
+// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
+// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "command-line": [
+// CHECK-NOT: "-fimplicit-modules"
+// CHECK-NOT: "-fimplicit-module-maps"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
+// CHECK: ],
+// CHECK-NEXT: "executable": "{{.*}}clang{{.*}}"
+// CHECK-NEXT: "file-deps": [
+// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
// CHECK-NEXT: }
-// CHECK-NEXT: ],
-// CHECK-NEXT: "command-line": [
-// CHECK: "-fno-implicit-modules"
-// CHECK: "-fno-implicit-module-maps"
-// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
-// CHECK: ],
-// CHECK-NEXT: "file-deps": [
-// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
-// CHECK-NEXT: ],
-// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
-// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: "commands": [
// CHECK-NEXT: {
-// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
-// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
+// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "context-hash": "[[HASH_H1]]",
+// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "command-line": [
+// CHECK-NOT: "-fimplicit-modules"
+// CHECK-NOT: "-fimplicit-module-maps"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
+// CHECK: ],
+// CHECK-NEXT: "executable": "{{.*}}clang{{.*}}"
+// CHECK-NEXT: "file-deps": [
+// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
// CHECK-NEXT: }
-// CHECK-NEXT: ],
-// CHECK-NEXT: "command-line": [
-// CHECK: "-fno-implicit-modules"
-// CHECK: "-fno-implicit-module-maps"
-// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm"
-// CHECK: ],
-// CHECK-NEXT: "file-deps": [
-// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
-// CHECK-NEXT: ],
-// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
+// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU_DINCLUDE:[A-Z0-9]+]]",
-// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: "commands": [
// CHECK-NEXT: {
-// CHECK-NEXT: "context-hash": "[[HASH_H1_DINCLUDE]]",
-// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: "clang-context-hash": "[[HASH_TU_DINCLUDE:[A-Z0-9]+]]",
+// CHECK-NEXT: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "context-hash": "[[HASH_H1_DINCLUDE]]",
+// CHECK-NEXT: "module-name": "header1"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "command-line": [
+// CHECK-NOT: "-fimplicit-modules"
+// CHECK-NOT: "-fimplicit-module-maps"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1_DINCLUDE]]/header1-{{[A-Z0-9]+}}.pcm"
+// CHECK: ],
+// CHECK-NEXT: "executable": "{{.*}}clang{{.*}}"
+// CHECK-NEXT: "file-deps": [
+// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input2.cpp"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input2.cpp"
// CHECK-NEXT: }
-// CHECK-NEXT: ],
-// CHECK-NEXT: "command-line": [
-// CHECK: "-fno-implicit-modules"
-// CHECK: "-fno-implicit-module-maps"
-// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1_DINCLUDE]]/header1-{{[A-Z0-9]+}}.pcm"
-// CHECK: ],
-// CHECK-NEXT: "file-deps": [
-// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input2.cpp"
-// CHECK-NEXT: ],
-// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input2.cpp"
+// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/modules-implicit-dot-private.m b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
index 6ae8eb2947067..4f9a20d8872f2 100644
--- a/clang/test/ClangScanDeps/modules-implicit-dot-private.m
+++ b/clang/test/ClangScanDeps/modules-implicit-dot-private.m
@@ -26,35 +26,35 @@
// CHECK: {
// CHECK-NEXT: "modules": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-module-deps": [],
+// CHECK: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW"
-// CHECK-NEXT: },
-// CHECK-NEXT: {
-// CHECK-NEXT: "clang-module-deps": [],
+// CHECK: },
+// CHECK: {
+// CHECK: "clang-module-deps": [],
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
// CHECK-NEXT: "command-line": [
// CHECK: ],
// CHECK-NEXT: "context-hash": "{{.*}}",
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
// CHECK-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h"
// CHECK-NEXT: ],
// CHECK-NEXT: "name": "FW_Private"
-// CHECK-NEXT: }
-// CHECK-NEXT: ],
+// CHECK: }
+// CHECK: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK: "clang-context-hash": "{{.*}}",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}",
@@ -66,16 +66,14 @@
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
-// CHECK: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
// CHECK: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
+// CHECK: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/tu.m"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.m"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
// RUN: %deps-to-rsp %t/result.json --module-name=FW > %t/FW.cc1.rsp
// RUN: %deps-to-rsp %t/result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
diff --git a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
index 973dc12192017..989bf5f1e4ca7 100644
--- a/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
+++ b/clang/test/ClangScanDeps/modules-incomplete-umbrella.c
@@ -67,7 +67,7 @@ framework module FW_Private {
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "translation-units": [
// CHECK_TU-NEXT: {
-// CHECK_TU-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK_TU: "clang-context-hash": "{{.*}}",
// CHECK_TU-NEXT: "clang-module-deps": [
// CHECK_TU-NEXT: {
// CHECK_TU-NEXT: "context-hash": "{{.*}}",
@@ -82,14 +82,12 @@ framework module FW_Private {
// CHECK_TU: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
// CHECK_TU: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
// CHECK_TU: ],
-// CHECK_TU-NEXT: "file-deps": [
+// CHECK_TU: "file-deps": [
// CHECK_TU-NEXT: "[[PREFIX]]/from_tu.m",
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h"
// CHECK_TU-NEXT: ],
// CHECK_TU-NEXT: "input-file": "[[PREFIX]]/from_tu.m"
// CHECK_TU-NEXT: }
-// CHECK_TU-NEXT: ]
-// CHECK_TU-NEXT: }
// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW > %t/FW.cc1.rsp
// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
@@ -175,7 +173,7 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "translation-units": [
// CHECK_MODULE-NEXT: {
-// CHECK_MODULE-NEXT: "clang-context-hash": "{{.*}}",
+// CHECK_MODULE: "clang-context-hash": "{{.*}}",
// CHECK_MODULE-NEXT: "clang-module-deps": [
// CHECK_MODULE-NEXT: {
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
@@ -184,13 +182,11 @@ module Mod { header "Mod.h" }
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "command-line": [
// CHECK_MODULE: ],
-// CHECK_MODULE-NEXT: "file-deps": [
+// CHECK_MODULE: "file-deps": [
// CHECK_MODULE-NEXT: "[[PREFIX]]/from_module.m"
// CHECK_MODULE-NEXT: ],
// CHECK_MODULE-NEXT: "input-file": "[[PREFIX]]/from_module.m"
// CHECK_MODULE-NEXT: }
-// CHECK_MODULE-NEXT: ]
-// CHECK_MODULE-NEXT: }
// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW > %t/FW.cc1.rsp
// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
diff --git a/clang/test/ClangScanDeps/modules-inferred.m b/clang/test/ClangScanDeps/modules-inferred.m
index ca1504e670c5e..ac0168324dd61 100644
--- a/clang/test/ClangScanDeps/modules-inferred.m
+++ b/clang/test/ClangScanDeps/modules-inferred.m
@@ -31,7 +31,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
+// CHECK: "clang-context-hash": "[[HASH_TU:[A-Z0-9]+]]",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_INFERRED]]",
@@ -40,10 +40,8 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/modules_cdb_input.cpp"
// CHECK-NEXT: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
index bdca47556a279..4dc1326077b88 100644
--- a/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
+++ b/clang/test/ClangScanDeps/modules-no-undeclared-includes.c
@@ -52,7 +52,7 @@ module User [no_undeclared_includes] { header "user.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "{{.*}}"
+// CHECK: "clang-context-hash": "{{.*}}"
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "{{.*}}"
@@ -61,13 +61,11 @@ module User [no_undeclared_includes] { header "user.h" }
// CHECK-NEXT: ],
// CHECK-NEXT: "command-line": [
// CHECK: ],
-// CHECK-NEXT: "file-deps": [
+// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/test.c"
// CHECK-NEXT: ],
// CHECK-NEXT: "input-file": "[[PREFIX]]/test.c"
// CHECK-NEXT: }
-// CHECK: ]
-// CHECK-NEXT: }
// RUN: %deps-to-rsp %t/result.json --module-name=User > %t/User.cc1.rsp
// RUN: %deps-to-rsp %t/result.json --tu-index=0 > %t/tu.rsp
diff --git a/clang/test/ClangScanDeps/modules-pch-common-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
index d6e54ffcbee9e..ae02fe7c8a9fc 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-submodule.c
@@ -36,7 +36,7 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "translation-units": [
// CHECK-PCH-NEXT: {
-// CHECK-PCH-NEXT: "clang-context-hash": "[[HASH_PCH:.*]]",
+// CHECK-PCH: "clang-context-hash": "[[HASH_PCH:.*]]",
// CHECK-PCH-NEXT: "clang-module-deps": [
// CHECK-PCH-NEXT: {
// CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON]]",
@@ -45,13 +45,11 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
-// CHECK-PCH-NEXT: "file-deps": [
+// CHECK-PCH: "file-deps": [
// CHECK-PCH-NEXT: "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "input-file": "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: }
-// CHECK-PCH-NEXT: ]
-// CHECK-PCH-NEXT: }
// Explicitly build the PCH:
//
@@ -85,7 +83,7 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "translation-units": [
// CHECK-TU-NEXT: {
-// CHECK-TU-NEXT: "clang-context-hash": "[[HASH_TU:.*]]",
+// CHECK-TU: "clang-context-hash": "[[HASH_TU:.*]]",
// CHECK-TU-NEXT: "clang-module-deps": [
// CHECK-TU-NEXT: {
// CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU]]"
@@ -94,14 +92,12 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
-// CHECK-TU-NEXT: "file-deps": [
+// CHECK-TU: "file-deps": [
// CHECK-TU-NEXT: "[[PREFIX]]/tu.c",
// CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-TU-NEXT: }
-// CHECK-TU-NEXT: ]
-// CHECK-TU-NEXT: }
// Explicitly build the TU:
//
diff --git a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
index 062881afda29f..aed49f4c2be61 100644
--- a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
+++ b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c
@@ -32,7 +32,7 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "translation-units": [
// CHECK-PCH-NEXT: {
-// CHECK-PCH-NEXT: "clang-context-hash": "[[HASH_PCH:.*]]",
+// CHECK-PCH: "clang-context-hash": "[[HASH_PCH:.*]]",
// CHECK-PCH-NEXT: "clang-module-deps": [
// CHECK-PCH-NEXT: {
// CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON]]",
@@ -41,13 +41,11 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
-// CHECK-PCH-NEXT: "file-deps": [
+// CHECK-PCH: "file-deps": [
// CHECK-PCH-NEXT: "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "input-file": "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: }
-// CHECK-PCH-NEXT: ]
-// CHECK-PCH-NEXT: }
// Explicitly build the PCH:
//
@@ -82,7 +80,7 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "translation-units": [
// CHECK-TU-NEXT: {
-// CHECK-TU-NEXT: "clang-context-hash": "[[HASH_TU:.*]]",
+// CHECK-TU: "clang-context-hash": "[[HASH_TU:.*]]",
// CHECK-TU-NEXT: "clang-module-deps": [
// CHECK-TU-NEXT: {
// CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU]]"
@@ -91,14 +89,12 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
-// CHECK-TU-NEXT: "file-deps": [
+// CHECK-TU: "file-deps": [
// CHECK-TU-NEXT: "[[PREFIX]]/tu.c",
// CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-TU-NEXT: }
-// CHECK-TU-NEXT: ]
-// CHECK-TU-NEXT: }
// Explicitly build the TU:
//
diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c
index 6a472084f9c04..1d46c89d57909 100644
--- a/clang/test/ClangScanDeps/modules-pch.c
+++ b/clang/test/ClangScanDeps/modules-pch.c
@@ -61,7 +61,7 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "translation-units": [
// CHECK-PCH-NEXT: {
-// CHECK-PCH-NEXT: "clang-context-hash": "[[HASH_PCH:.*]]",
+// CHECK-PCH: "clang-context-hash": "[[HASH_PCH:.*]]",
// CHECK-PCH-NEXT: "clang-module-deps": [
// CHECK-PCH-NEXT: {
// CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON_1]]",
@@ -74,13 +74,11 @@
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "command-line": [
// CHECK-PCH: ],
-// CHECK-PCH-NEXT: "file-deps": [
+// CHECK-PCH: "file-deps": [
// CHECK-PCH-NEXT: "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: ],
// CHECK-PCH-NEXT: "input-file": "[[PREFIX]]/pch.h"
// CHECK-PCH-NEXT: }
-// CHECK-PCH-NEXT: ]
-// CHECK-PCH-NEXT: }
// Explicitly build the PCH:
//
@@ -118,7 +116,7 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "translation-units": [
// CHECK-TU-NEXT: {
-// CHECK-TU-NEXT: "clang-context-hash": "[[HASH_TU:.*]]",
+// CHECK-TU: "clang-context-hash": "[[HASH_TU:.*]]",
// CHECK-TU-NEXT: "clang-module-deps": [
// CHECK-TU-NEXT: {
// CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU]]",
@@ -127,14 +125,12 @@
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "command-line": [
// CHECK-TU: ],
-// CHECK-TU-NEXT: "file-deps": [
+// CHECK-TU: "file-deps": [
// CHECK-TU-NEXT: "[[PREFIX]]/tu.c",
// CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch"
// CHECK-TU-NEXT: ],
// CHECK-TU-NEXT: "input-file": "[[PREFIX]]/tu.c"
// CHECK-TU-NEXT: }
-// CHECK-TU-NEXT: ]
-// CHECK-TU-NEXT: }
// Explicitly build the TU:
//
@@ -168,7 +164,7 @@
// CHECK-TU-WITH-COMMON-NEXT: ],
// CHECK-TU-WITH-COMMON-NEXT: "translation-units": [
// CHECK-TU-WITH-COMMON-NEXT: {
-// CHECK-TU-WITH-COMMON-NEXT: "clang-context-hash": "[[HASH_TU_WITH_COMMON:.*]]",
+// CHECK-TU-WITH-COMMON: "clang-context-hash": "[[HASH_TU_WITH_COMMON:.*]]",
// CHECK-TU-WITH-COMMON-NEXT: "clang-module-deps": [
// CHECK-TU-WITH-COMMON-NEXT: {
// CHECK-TU-WITH-COMMON-NEXT: "context-hash": "[[HASH_MOD_TU_WITH_COMMON]]",
@@ -178,14 +174,12 @@
// CHECK-TU-WITH-COMMON-NEXT: "command-line": [
// CHECK-TU-WITH-COMMON: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm"
// CHECK-TU-WITH-COMMON: ],
-// CHECK-TU-WITH-COMMON-NEXT: "file-deps": [
+// CHECK-TU-WITH-COMMON: "file-deps": [
// CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/tu_with_common.c",
// CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/pch.h.gch"
// CHECK-TU-WITH-COMMON-NEXT: ],
// CHECK-TU-WITH-COMMON-NEXT: "input-file": "[[PREFIX]]/tu_with_common.c"
// CHECK-TU-WITH-COMMON-NEXT: }
-// CHECK-TU-WITH-COMMON-NEXT: ]
-// CHECK-TU-WITH-COMMON-NEXT: }
// Explicitly build the TU that has common modules with the PCH:
//
diff --git a/clang/test/ClangScanDeps/multiple-commands.c b/clang/test/ClangScanDeps/multiple-commands.c
new file mode 100644
index 0000000000000..6640d40e6e7c6
--- /dev/null
+++ b/clang/test/ClangScanDeps/multiple-commands.c
@@ -0,0 +1,173 @@
+// Test scanning when the driver requires multiple jobs. E.g. with -save-temps
+// there will be separate -E, -emit-llvm-bc, -S, and -cc1as jobs, which should
+// each result in a "command" in the output.
+
+// We use an x86_64-apple-darwin target to avoid host-dependent behaviour in
+// the driver. Platforms without an integrated assembler have
diff erent commands
+// REQUIRES: x86-registered-target
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json
+
+// RUN: clang-scan-deps -compilation-database %t/cdb.json -module-files-dir %t/modules \
+// RUN: -j 1 -format experimental-full -mode preprocess-dependency-directives \
+// RUN: > %t/deps.json
+
+// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
+
+// Build the -save-temps + -fmodules case
+// RUN: %deps-to-rsp %t/deps.json --module-name=Mod > %t/Mod.rsp
+// RUN: %deps-to-rsp %t/deps.json --tu-index 1 --tu-cmd-index 0 > %t/tu-cpp.rsp
+// RUN: %deps-to-rsp %t/deps.json --tu-index 1 --tu-cmd-index 1 > %t/tu-emit-ir.rsp
+// RUN: %deps-to-rsp %t/deps.json --tu-index 1 --tu-cmd-index 2 > %t/tu-emit-asm.rsp
+// RUN: %deps-to-rsp %t/deps.json --tu-index 1 --tu-cmd-index 3 > %t/tu-cc1as.rsp
+// RUN: %clang @%t/Mod.rsp
+// RUN: %clang @%t/tu-cpp.rsp
+// RUN: ls %t/tu_save_temps_module.i
+// RUN: %clang @%t/tu-emit-ir.rsp
+// RUN: ls %t/tu_save_temps_module.bc
+// RUN: %clang @%t/tu-emit-asm.rsp
+// RUN: ls %t/tu_save_temps_module.s
+// RUN: %clang @%t/tu-cc1as.rsp
+// RUN: ls %t/tu_save_temps_module.o
+
+
+// CHECK: "modules": [
+// CHECK-NEXT: {
+// CHECK: "clang-modulemap-file": "[[PREFIX]]{{.}}module.modulemap"
+// CHECK: "name": "Mod"
+// CHECK: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: "translation-units": [
+// CHECK-NEXT: {
+// CHECK: "commands": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "clang-context-hash":
+// CHECK-NEXT: "clang-module-deps": []
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_no_integrated_cpp{{.*}}.i"
+// CHECK: "-E"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_no_integrated_cpp.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: {
+// CHECK-NEXT: "clang-context-hash":
+// CHECK-NEXT: "clang-module-deps": []
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_no_integrated_cpp.o"
+// CHECK: "-emit-obj"
+// CHECK: "{{.*}}tu_no_integrated_cpp{{.*}}.i"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_no_integrated_cpp.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: {
+// CHECK-NEXT: "commands": [
+// CHECK-NEXT: {
+// CHECK: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK: "module-name": "Mod"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_save_temps_module.i"
+// CHECK: "-E"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]{{.}}modules{{.*}}Mod-{{.*}}.pcm"
+// CHECK: "{{.*}}tu_save_temps_module.c"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_save_temps_module.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: {
+// CHECK: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK: "module-name": "Mod"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_save_temps_module.bc"
+// CHECK: "-emit-llvm-bc"
+// CHECK: "{{.*}}tu_save_temps_module.i"
+// CHECK: "-fmodule-file={{.*}}[[PREFIX]]{{.}}modules{{.*}}Mod-{{.*}}.pcm"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_save_temps_module.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: {
+// CHECK: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK: "module-name": "Mod"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_save_temps_module.s"
+// CHECK: "-S"
+// CHECK: "{{.*}}tu_save_temps_module.bc"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_save_temps_module.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: {
+// CHECK: "clang-module-deps": [
+// CHECK-NEXT: {
+// CHECK: "module-name": "Mod"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: "command-line": [
+// CHECK-NEXT: "-cc1as"
+// CHECK: "-o"
+// CHECK-NEXT: "{{.*}}tu_save_temps_module.o"
+// CHECK: "{{.*}}tu_save_temps_module.s"
+// CHECK: ]
+// CHECK-NEXT: "executable": "clang_tool"
+// CHECK: "input-file": "[[PREFIX]]{{.}}tu_save_temps_module.c"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+
+//--- cdb.json.in
+[
+ {
+ "directory": "DIR"
+ "command": "clang_tool -target x86_64-apple-darwin -c DIR/tu_no_integrated_cpp.c -no-integrated-cpp -o DIR/tu_no_integrated_cpp.o"
+ "file": "DIR/tu_no_integrated_cpp.c"
+ },
+ {
+ "directory": "DIR"
+ "command": "clang_tool -target x86_64-apple-darwin -c DIR/tu_save_temps_module.c -save-temps=obj -o DIR/tu_save_temps_module.o -fmodules -fimplicit-modules -fimplicit-module-maps"
+ "file": "DIR/tu_save_temps_module.c"
+ }
+]
+
+//--- plain_header.h
+void foo(void);
+
+//--- module_header.h
+void bar(void);
+
+//--- module.modulemap
+module Mod { header "module_header.h" }
+
+//--- tu_no_integrated_cpp.c
+#include "plain_header.h"
+void tu_no_integrated_cpp(void) { foo(); }
+
+//--- tu_save_temps_module.c
+#include "module_header.h"
+void tu_save_temps(void) { bar(); }
diff --git a/clang/test/ClangScanDeps/removed-args.c b/clang/test/ClangScanDeps/removed-args.c
index 8c07ca8d1f7e9..12d6ab1428f52 100644
--- a/clang/test/ClangScanDeps/removed-args.c
+++ b/clang/test/ClangScanDeps/removed-args.c
@@ -61,7 +61,7 @@
// CHECK-NEXT: ],
// CHECK-NEXT: "translation-units": [
// CHECK-NEXT: {
-// CHECK-NEXT: "clang-context-hash": "[[HASH_TU:.*]]",
+// CHECK: "clang-context-hash": "[[HASH_TU:.*]]",
// CHECK-NEXT: "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT: "context-hash": "[[HASH_MOD_HEADER]]",
@@ -73,13 +73,11 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: "command-line": [
-// CHECK-NEXT: "-fsyntax-only",
+// CHECK-NEXT: "-cc1",
// CHECK-NOT: "-fmodules-cache-path=
// CHECK-NOT: "-fmodules-validate-once-per-build-session"
+// CHECK-NOT: "-fbuild-session-timestamp=
// CHECK-NOT: "-fbuild-session-file=
// CHECK-NOT: "-fmodules-prune-interval=
// CHECK-NOT: "-fmodules-prune-after=
// CHECK: ],
-// CHECK: }
-// CHECK-NEXT: ]
-// CHECK-NEXT: }
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 2d3415145bc62..28da64f9992e3 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -182,6 +182,11 @@ llvm::cl::list<std::string> ModuleDepTargets(
llvm::cl::desc("The names of dependency targets for the dependency file"),
llvm::cl::cat(DependencyScannerCategory));
+llvm::cl::opt<bool> DeprecatedDriverCommand(
+ "deprecated-driver-command", llvm::cl::Optional,
+ llvm::cl::desc("use a single driver command to build the tu (deprecated)"),
+ llvm::cl::cat(DependencyScannerCategory));
+
enum ResourceDirRecipeKind {
RDRK_ModifyCompilerPath,
RDRK_InvokeCompiler,
@@ -256,7 +261,7 @@ class FullDeps {
public:
void mergeDeps(StringRef Input, FullDependenciesResult FDR,
size_t InputIndex) {
- const FullDependencies &FD = FDR.FullDeps;
+ FullDependencies &FD = FDR.FullDeps;
InputDeps ID;
ID.FileName = std::string(Input);
@@ -274,7 +279,8 @@ class FullDeps {
Modules.insert(I, {{MD.ID, InputIndex}, std::move(MD)});
}
- ID.CommandLine = FD.CommandLine;
+ ID.DriverCommandLine = std::move(FD.DriverCommandLine);
+ ID.Commands = std::move(FD.Commands);
Inputs.push_back(std::move(ID));
}
@@ -311,14 +317,33 @@ class FullDeps {
Array TUs;
for (auto &&I : Inputs) {
- Object O{
- {"input-file", I.FileName},
- {"clang-context-hash", I.ContextHash},
- {"file-deps", I.FileDeps},
- {"clang-module-deps", toJSONSorted(I.ModuleDeps)},
- {"command-line", I.CommandLine},
- };
- TUs.push_back(std::move(O));
+ Array Commands;
+ if (I.DriverCommandLine.empty()) {
+ for (const auto &Cmd : I.Commands) {
+ Object O{
+ {"input-file", I.FileName},
+ {"clang-context-hash", I.ContextHash},
+ {"file-deps", I.FileDeps},
+ {"clang-module-deps", toJSONSorted(I.ModuleDeps)},
+ {"executable", Cmd.Executable},
+ {"command-line", Cmd.Arguments},
+ };
+ Commands.push_back(std::move(O));
+ }
+ } else {
+ Object O{
+ {"input-file", I.FileName},
+ {"clang-context-hash", I.ContextHash},
+ {"file-deps", I.FileDeps},
+ {"clang-module-deps", toJSONSorted(I.ModuleDeps)},
+ {"executable", "clang"},
+ {"command-line", I.DriverCommandLine},
+ };
+ Commands.push_back(std::move(O));
+ }
+ TUs.push_back(Object{
+ {"commands", std::move(Commands)},
+ });
}
Object Output{
@@ -353,7 +378,8 @@ class FullDeps {
std::string ContextHash;
std::vector<std::string> FileDeps;
std::vector<ModuleID> ModuleDeps;
- std::vector<std::string> CommandLine;
+ std::vector<std::string> DriverCommandLine;
+ std::vector<Command> Commands;
};
std::mutex Lock;
@@ -559,6 +585,14 @@ int main(int argc, const char **argv) {
if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS,
Errs))
HadErrors = true;
+ } else if (DeprecatedDriverCommand) {
+ auto MaybeFullDeps =
+ WorkerTools[I]->getFullDependenciesLegacyDriverCommand(
+ Input->CommandLine, CWD, AlreadySeenModules, LookupOutput,
+ MaybeModuleName);
+ if (handleFullDependencyToolResult(Filename, MaybeFullDeps, FD,
+ LocalIndex, DependencyOS, Errs))
+ HadErrors = true;
} else {
auto MaybeFullDeps = WorkerTools[I]->getFullDependencies(
Input->CommandLine, CWD, AlreadySeenModules, LookupOutput,
diff --git a/clang/utils/module-deps-to-rsp.py b/clang/utils/module-deps-to-rsp.py
index 0688c40a58956..e017917af61f3 100755
--- a/clang/utils/module-deps-to-rsp.py
+++ b/clang/utils/module-deps-to-rsp.py
@@ -48,6 +48,9 @@ def main():
type=str)
action.add_argument("--tu-index", help="The index of the translation unit to get arguments for",
type=int)
+ parser.add_argument("--tu-cmd-index",
+ help="The index of the command within the translation unit (default=0)",
+ type=int, default=0)
args = parser.parse_args()
full_deps = parseFullDeps(json.load(open(args.full_deps_file, 'r')))
@@ -58,7 +61,8 @@ def main():
if args.module_name:
cmd = findModule(args.module_name, full_deps)['command-line']
elif args.tu_index != None:
- cmd = full_deps.translation_units[args.tu_index]['command-line']
+ tu = full_deps.translation_units[args.tu_index]
+ cmd = tu['commands'][args.tu_cmd_index]['command-line']
print(" ".join(map(quote, cmd)))
except:
More information about the cfe-commits
mailing list