Skip to content

Commit 6b4de7b

Browse files
cpsughruejansvoboda11
authored andcommitted
[clang][deps] add support for dependency scanning with cc1 command line
Allow users to run a dependency scan with a cc1 command line in addition to a driver command line. DependencyScanningAction was already being run with a cc1 command line, but DependencyScanningWorker::computeDependencies assumed that it was always provided a driver command line. Now DependencyScanningWorker::computeDependencies can handle cc1 command lines too. Reviewed By: jansvoboda11 Differential Revision: https://reviews.llvm.org/D156234
1 parent 00769d6 commit 6b4de7b

File tree

2 files changed

+83
-31
lines changed

2 files changed

+83
-31
lines changed

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,36 @@ static bool forEachDriverJob(
385385
if (!Compilation)
386386
return false;
387387

388+
if (Compilation->containsError())
389+
return false;
390+
388391
for (const driver::Command &Job : Compilation->getJobs()) {
389392
if (!Callback(Job))
390393
return false;
391394
}
392395
return true;
393396
}
394397

398+
static bool createAndRunToolInvocation(
399+
std::vector<std::string> CommandLine, DependencyScanningAction &Action,
400+
FileManager &FM,
401+
std::shared_ptr<clang::PCHContainerOperations> &PCHContainerOps,
402+
DiagnosticsEngine &Diags, DependencyConsumer &Consumer) {
403+
404+
// Save executable path before providing CommandLine to ToolInvocation
405+
std::string Executable = CommandLine[0];
406+
ToolInvocation Invocation(std::move(CommandLine), &Action, &FM,
407+
PCHContainerOps);
408+
Invocation.setDiagnosticConsumer(Diags.getClient());
409+
Invocation.setDiagnosticOptions(&Diags.getDiagnosticOptions());
410+
if (!Invocation.run())
411+
return false;
412+
413+
std::vector<std::string> Args = Action.takeLastCC1Arguments();
414+
Consumer.handleBuildCommand({std::move(Executable), std::move(Args)});
415+
return true;
416+
}
417+
395418
bool DependencyScanningWorker::computeDependencies(
396419
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
397420
DependencyConsumer &Consumer, DependencyActionController &Controller,
@@ -454,37 +477,37 @@ bool DependencyScanningWorker::computeDependencies(
454477
DependencyScanningAction Action(WorkingDirectory, Consumer, Controller, DepFS,
455478
Format, OptimizeArgs, EagerLoadModules,
456479
DisableFree, ModuleName);
457-
bool Success = forEachDriverJob(
458-
FinalCommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
459-
if (StringRef(Cmd.getCreator().getName()) != "clang") {
460-
// Non-clang command. Just pass through to the dependency
461-
// consumer.
462-
Consumer.handleBuildCommand(
463-
{Cmd.getExecutable(),
464-
{Cmd.getArguments().begin(), Cmd.getArguments().end()}});
465-
return true;
466-
}
467-
468-
std::vector<std::string> Argv;
469-
Argv.push_back(Cmd.getExecutable());
470-
Argv.insert(Argv.end(), Cmd.getArguments().begin(),
471-
Cmd.getArguments().end());
472-
473-
// Create an invocation that uses the underlying file
474-
// system to ensure that any file system requests that
475-
// are made by the driver do not go through the
476-
// dependency scanning filesystem.
477-
ToolInvocation Invocation(std::move(Argv), &Action, &*FileMgr,
478-
PCHContainerOps);
479-
Invocation.setDiagnosticConsumer(Diags->getClient());
480-
Invocation.setDiagnosticOptions(&Diags->getDiagnosticOptions());
481-
if (!Invocation.run())
482-
return false;
483-
484-
std::vector<std::string> Args = Action.takeLastCC1Arguments();
485-
Consumer.handleBuildCommand({Cmd.getExecutable(), std::move(Args)});
486-
return true;
487-
});
480+
481+
bool Success = false;
482+
if (FinalCommandLine[1] == "-cc1") {
483+
Success = createAndRunToolInvocation(FinalCommandLine, Action, *FileMgr,
484+
PCHContainerOps, *Diags, Consumer);
485+
} else {
486+
Success = forEachDriverJob(
487+
FinalCommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
488+
if (StringRef(Cmd.getCreator().getName()) != "clang") {
489+
// Non-clang command. Just pass through to the dependency
490+
// consumer.
491+
Consumer.handleBuildCommand(
492+
{Cmd.getExecutable(),
493+
{Cmd.getArguments().begin(), Cmd.getArguments().end()}});
494+
return true;
495+
}
496+
497+
// Insert -cc1 comand line options into Argv
498+
std::vector<std::string> Argv;
499+
Argv.push_back(Cmd.getExecutable());
500+
Argv.insert(Argv.end(), Cmd.getArguments().begin(),
501+
Cmd.getArguments().end());
502+
503+
// Create an invocation that uses the underlying file
504+
// system to ensure that any file system requests that
505+
// are made by the driver do not go through the
506+
// dependency scanning filesystem.
507+
return createAndRunToolInvocation(std::move(Argv), Action, *FileMgr,
508+
PCHContainerOps, *Diags, Consumer);
509+
});
510+
}
488511

489512
if (Success && !Action.hasScanned())
490513
Diags->Report(diag::err_fe_expected_compiler_job)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Check that clang-scan-deps works with cc1 command lines
2+
3+
// RUN: rm -rf %t
4+
// RUN: split-file %s %t
5+
6+
7+
//--- modules_cc1.cpp
8+
#include "header.h"
9+
10+
//--- header.h
11+
12+
//--- module.modulemap
13+
module header1 { header "header.h" }
14+
15+
//--- cdb.json.template
16+
[{
17+
"file": "DIR/modules_cc1.cpp",
18+
"directory": "DIR",
19+
"command": "clang -cc1 DIR/modules_cc1.cpp -fimplicit-module-maps -o modules_cc1.o"
20+
}]
21+
22+
// RUN: sed "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
23+
// RUN: clang-scan-deps -compilation-database %t/cdb.json -j 1 -mode preprocess-dependency-directives > %t/result
24+
// RUN: cat %t/result | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
25+
26+
// CHECK: modules_cc1.o:
27+
// CHECK-NEXT: [[PREFIX]]/modules_cc1.cpp
28+
// CHECK-NEXT: [[PREFIX]]/module.modulemap
29+
// CHECK-NEXT: [[PREFIX]]/header.h

0 commit comments

Comments
 (0)