[clang][deps] Support single-file mode for all formats (#88764)

The `clang-scan-deps` tool can be used for fast scanning of batches of
compilation commands passed in via the `-compilation-database` option.
This gets awkward in our tests where we have to resort to using
`.in`/`.template` JSON files and running them through `sed` in order to
embed LIT's `%t` variable into them. However, most of our tests only
need to pass single compilation command, so this dance is entirely
unnecessary.

This patch makes sure the existing "per-file" mode (where the
compilation command is passed in-line after the `--` argument) works for
all output formats, not only `P1689`.
This commit is contained in:
Jan Svoboda 2024-04-16 19:47:52 -07:00 committed by GitHub
parent e6ecff8d95
commit eafd515eca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 52 deletions

View File

@ -1,23 +1,10 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
//--- missing_tu.json.in
[{
"directory": "DIR",
"command": "clang -fsyntax-only DIR/missing_tu.c",
"file": "DIR/missing_tu.c"
}]
//--- missing_header.json.in
[{
"directory": "DIR",
"command": "clang -fsyntax-only DIR/missing_header.c",
"file": "DIR/missing_header.c"
}]
//--- missing_header.c
#include "missing.h"
// RUN: sed -e "s|DIR|%/t|g" %t/missing_tu.json.in > %t/missing_tu.json
// RUN: not clang-scan-deps -compilation-database %t/missing_tu.json 2>%t/missing_tu.errs
// RUN: not clang-scan-deps -- %clang -c %t/missing_tu.c 2>%t/missing_tu.errs
// RUN: echo EOF >> %t/missing_tu.errs
// RUN: cat %t/missing_tu.errs | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-MISSING-TU -DPREFIX=%/t
// CHECK-MISSING-TU: Error while scanning dependencies for [[PREFIX]]/missing_tu.c
@ -26,8 +13,7 @@
// CHECK-MISSING-TU-NEXT: error:
// CHECK-MISSING-TU-NEXT: EOF
// RUN: sed -e "s|DIR|%/t|g" %t/missing_header.json.in > %t/missing_header.json
// RUN: not clang-scan-deps -compilation-database %t/missing_header.json 2>%t/missing_header.errs
// RUN: not clang-scan-deps -- %clang -c %t/missing_header.c 2>%t/missing_header.errs
// RUN: echo EOF >> %t/missing_header.errs
// RUN: cat %t/missing_header.errs | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-MISSING-HEADER -DPREFIX=%/t
// CHECK-MISSING-HEADER: Error while scanning dependencies for [[PREFIX]]/missing_header.c

View File

@ -98,8 +98,8 @@ static bool RoundTripArgs = DoRoundTripDefault;
static void ParseArgs(int argc, char **argv) {
ScanDepsOptTable Tbl;
llvm::StringRef ToolName = argv[0];
llvm::BumpPtrAllocator A;
llvm::StringSaver Saver{A};
llvm::BumpPtrAllocator Alloc;
llvm::StringSaver Saver{Alloc};
llvm::opt::InputArgList Args =
Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
llvm::errs() << Msg << '\n';
@ -186,14 +186,8 @@ static void ParseArgs(int argc, char **argv) {
}
}
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_compilation_database_EQ)) {
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_compilation_database_EQ))
CompilationDB = A->getValue();
} else if (Format != ScanningOutputFormat::P1689) {
llvm::errs() << ToolName
<< ": for the --compiilation-database option: must be "
"specified at least once!";
std::exit(1);
}
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_name_EQ))
ModuleName = A->getValue();
@ -225,9 +219,8 @@ static void ParseArgs(int argc, char **argv) {
RoundTripArgs = Args.hasArg(OPT_round_trip_args);
if (auto *A = Args.getLastArgNoClaim(OPT_DASH_DASH))
CommandLine.insert(CommandLine.end(), A->getValues().begin(),
A->getValues().end());
if (const llvm::opt::Arg *A = Args.getLastArgNoClaim(OPT_DASH_DASH))
CommandLine.assign(A->getValues().begin(), A->getValues().end());
}
class SharedStream {
@ -694,38 +687,28 @@ static std::string getModuleCachePath(ArrayRef<std::string> Args) {
return std::string(Path);
}
// getCompilationDataBase - If -compilation-database is set, load the
// compilation database from the specified file. Otherwise if the we're
// generating P1689 format, trying to generate the compilation database
// form specified command line after the positional parameter "--".
/// Attempts to construct the compilation database from '-compilation-database'
/// or from the arguments following the positional '--'.
static std::unique_ptr<tooling::CompilationDatabase>
getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
getCompilationDatabase(int argc, char **argv, std::string &ErrorMessage) {
ParseArgs(argc, argv);
if (!(CommandLine.empty() ^ CompilationDB.empty())) {
llvm::errs() << "The compilation command line must be provided either via "
"'-compilation-database' or after '--'.";
return nullptr;
}
if (!CompilationDB.empty())
return tooling::JSONCompilationDatabase::loadFromFile(
CompilationDB, ErrorMessage,
tooling::JSONCommandLineSyntax::AutoDetect);
if (Format != ScanningOutputFormat::P1689) {
llvm::errs() << "the --compilation-database option: must be specified at "
"least once!";
return nullptr;
}
// Trying to get the input file, the output file and the command line options
// from the positional parameter "--".
char **DoubleDash = std::find(argv, argv + argc, StringRef("--"));
if (DoubleDash == argv + argc) {
llvm::errs() << "The command line arguments is required after '--' in "
"P1689 per file mode.";
return nullptr;
}
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions);
driver::Driver TheDriver(CommandLine[0], llvm::sys::getDefaultTargetTriple(),
*Diags);
TheDriver.setCheckInputsExist(false);
std::unique_ptr<driver::Compilation> C(
TheDriver.BuildCompilation(CommandLine));
if (!C || C->getJobs().empty())
@ -740,7 +723,8 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
FrontendOptions &FEOpts = CI->getFrontendOpts();
if (FEOpts.Inputs.size() != 1) {
llvm::errs() << "Only one input file is allowed in P1689 per file mode.";
llvm::errs()
<< "Exactly one input file is required in the per-file mode ('--').\n";
return nullptr;
}
@ -749,8 +733,9 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
auto LastCmd = C->getJobs().end();
LastCmd--;
if (LastCmd->getOutputFilenames().size() != 1) {
llvm::errs() << "The command line should provide exactly one output file "
"in P1689 per file mode.\n";
llvm::errs()
<< "Exactly one output file is required in the per-file mode ('--').\n";
return nullptr;
}
StringRef OutputFile = LastCmd->getOutputFilenames().front();
@ -790,7 +775,7 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
std::string ErrorMessage;
std::unique_ptr<tooling::CompilationDatabase> Compilations =
getCompilationDataBase(argc, argv, ErrorMessage);
getCompilationDatabase(argc, argv, ErrorMessage);
if (!Compilations) {
llvm::errs() << ErrorMessage << "\n";
return 1;