Skip to content

Commit efbeb41

Browse files
committed
[clang][deps] Add -o flag to specify output path (llvm#88767)
This makes it possible to pass "-o /dev/null" to `clang-scan-deps` and skip some potentially expensive work, making timings less noisy. Also removes the need for stream redirection. (cherry picked from commit 6a4eaf9)
1 parent 04bb9f4 commit efbeb41

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

clang/test/ClangScanDeps/module-format.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
// RUN: rm -f %t/cdb_pch.json
1717
// RUN: sed "s|DIR|%/t|g" %S/Inputs/modules-pch/cdb_pch.json > %t/cdb_pch.json
1818
// RUN: clang-scan-deps -compilation-database %t/cdb_pch.json -format experimental-full \
19-
// RUN: -module-files-dir %t/build > %t/result_pch.json
19+
// RUN: -module-files-dir %t/build -o %t/result_pch.json
2020

2121
// Explicitly build the PCH:
2222
//

clang/tools/clang-scan-deps/ClangScanDeps.cpp

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ enum ResourceDirRecipeKind {
8181
RDRK_InvokeCompiler,
8282
};
8383

84+
static std::string OutputFileName = "-";
8485
static ScanningMode ScanMode = ScanningMode::DependencyDirectivesScan;
8586
static ScanningOutputFormat Format = ScanningOutputFormat::Make;
8687
static ScanningOptimizations OptimizeArgs;
@@ -196,6 +197,9 @@ static void ParseArgs(int argc, char **argv) {
196197
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_module_files_dir_EQ))
197198
ModuleFilesDir = A->getValue();
198199

200+
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_o))
201+
OutputFileName = A->getValue();
202+
199203
EagerLoadModules = Args.hasArg(OPT_eager_load_pcm);
200204

201205
if (const llvm::opt::Arg *A = Args.getLastArg(OPT_j)) {
@@ -514,7 +518,7 @@ handleMakeDependencyToolResult(const std::string &Input,
514518

515519
static bool handleTreeDependencyToolResult(
516520
llvm::cas::ObjectStore &CAS, const std::string &Input,
517-
llvm::Expected<llvm::cas::ObjectProxy> &MaybeTree, SharedStream &OS,
521+
llvm::Expected<llvm::cas::ObjectProxy> &MaybeTree, llvm::raw_ostream &OS,
518522
SharedStream &Errs) {
519523
if (!MaybeTree) {
520524
llvm::handleAllErrors(
@@ -527,17 +531,15 @@ static bool handleTreeDependencyToolResult(
527531
});
528532
return true;
529533
}
530-
OS.applyLocked([&](llvm::raw_ostream &OS) {
531-
OS << "tree " << MaybeTree->getID() << " for '" << Input << "'\n";
532-
});
534+
OS << "tree " << MaybeTree->getID() << " for '" << Input << "'\n";
533535
return false;
534536
}
535537

536538
static bool
537539
handleIncludeTreeToolResult(llvm::cas::ObjectStore &CAS,
538540
const std::string &Input,
539541
Expected<cas::IncludeTreeRoot> &MaybeTree,
540-
SharedStream &OS, SharedStream &Errs) {
542+
llvm::raw_ostream &OS, SharedStream &Errs) {
541543
if (!MaybeTree) {
542544
llvm::handleAllErrors(
543545
MaybeTree.takeError(), [&Input, &Errs](llvm::StringError &Err) {
@@ -559,11 +561,9 @@ handleIncludeTreeToolResult(llvm::cas::ObjectStore &CAS,
559561
};
560562

561563
std::optional<llvm::Error> E;
562-
OS.applyLocked([&](llvm::raw_ostream &OS) {
563-
MaybeTree->getID().print(OS);
564-
OS << " - " << Input << "\n";
565-
E = MaybeTree->print(OS);
566-
});
564+
MaybeTree->getID().print(OS);
565+
OS << " - " << Input << "\n";
566+
E = MaybeTree->print(OS);
567567
if (*E)
568568
return printError(std::move(*E));
569569
return false;
@@ -682,6 +682,11 @@ class FullDeps {
682682
}
683683

684684
void printFullOutput(raw_ostream &OS) {
685+
// Skip sorting modules and constructing the JSON object if the output
686+
// cannot be observed anyway. This makes timings less noisy.
687+
if (&OS == &llvm::nulls())
688+
return;
689+
685690
// Sort the modules by name to get a deterministic order.
686691
std::vector<IndexedModuleID> ModuleIDs;
687692
for (auto &&M : Modules)
@@ -1142,8 +1147,25 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
11421147
});
11431148

11441149
SharedStream Errs(llvm::errs());
1145-
// Print out the dependency results to STDOUT by default.
1146-
SharedStream DependencyOS(llvm::outs());
1150+
1151+
std::optional<llvm::raw_fd_ostream> FileOS;
1152+
llvm::raw_ostream &ThreadUnsafeDependencyOS = [&]() -> llvm::raw_ostream & {
1153+
if (OutputFileName == "-")
1154+
return llvm::outs();
1155+
1156+
if (OutputFileName == "/dev/null")
1157+
return llvm::nulls();
1158+
1159+
std::error_code EC;
1160+
FileOS.emplace(OutputFileName, EC);
1161+
if (EC) {
1162+
llvm::errs() << "Failed to open output file '" << OutputFileName
1163+
<< "': " << llvm::errorCodeToError(EC) << '\n';
1164+
std::exit(1);
1165+
}
1166+
return *FileOS;
1167+
}();
1168+
SharedStream DependencyOS(ThreadUnsafeDependencyOS);
11471169

11481170
auto DiagsConsumer = std::make_unique<TextDiagnosticPrinter>(
11491171
llvm::errs(), new DiagnosticOptions(), false);
@@ -1361,23 +1383,23 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
13611383
if (Format == ScanningOutputFormat::Tree) {
13621384
for (auto &TreeResult : TreeResults) {
13631385
if (handleTreeDependencyToolResult(*CAS, TreeResult.Filename,
1364-
*TreeResult.MaybeTree, DependencyOS,
1365-
Errs))
1386+
*TreeResult.MaybeTree,
1387+
ThreadUnsafeDependencyOS, Errs))
13661388
HadErrors = true;
13671389
}
13681390
} else if (Format == ScanningOutputFormat::IncludeTree) {
13691391
for (auto &TreeResult : TreeResults) {
13701392
if (handleIncludeTreeToolResult(*CAS, TreeResult.Filename,
13711393
*TreeResult.MaybeIncludeTree,
1372-
DependencyOS, Errs))
1394+
ThreadUnsafeDependencyOS, Errs))
13731395
HadErrors = true;
13741396
}
13751397
} else if (Format == ScanningOutputFormat::Full ||
13761398
Format == ScanningOutputFormat::FullTree ||
13771399
Format == ScanningOutputFormat::FullIncludeTree) {
1378-
FD->printFullOutput(llvm::outs());
1400+
FD->printFullOutput(ThreadUnsafeDependencyOS);
13791401
} else if (Format == ScanningOutputFormat::P1689)
1380-
PD.printDependencies(llvm::outs());
1402+
PD.printDependencies(ThreadUnsafeDependencyOS);
13811403

13821404
return HadErrors;
13831405
}

clang/tools/clang-scan-deps/Opts.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ multiclass Eq<string name, string help> {
1111
def help : Flag<["--"], "help">, HelpText<"Display this help">;
1212
def version : Flag<["--"], "version">, HelpText<"Display the version">;
1313

14+
def o : Arg<"o", "Destination of the primary output">;
15+
1416
defm mode : Eq<"mode", "The preprocessing mode used to compute the dependencies">;
1517

1618
defm format : Eq<"format", "The output format for the dependencies">;

0 commit comments

Comments
 (0)