@@ -81,6 +81,7 @@ enum ResourceDirRecipeKind {
81
81
RDRK_InvokeCompiler,
82
82
};
83
83
84
+ static std::string OutputFileName = " -" ;
84
85
static ScanningMode ScanMode = ScanningMode::DependencyDirectivesScan;
85
86
static ScanningOutputFormat Format = ScanningOutputFormat::Make;
86
87
static ScanningOptimizations OptimizeArgs;
@@ -196,6 +197,9 @@ static void ParseArgs(int argc, char **argv) {
196
197
if (const llvm::opt::Arg *A = Args.getLastArg (OPT_module_files_dir_EQ))
197
198
ModuleFilesDir = A->getValue ();
198
199
200
+ if (const llvm::opt::Arg *A = Args.getLastArg (OPT_o))
201
+ OutputFileName = A->getValue ();
202
+
199
203
EagerLoadModules = Args.hasArg (OPT_eager_load_pcm);
200
204
201
205
if (const llvm::opt::Arg *A = Args.getLastArg (OPT_j)) {
@@ -514,7 +518,7 @@ handleMakeDependencyToolResult(const std::string &Input,
514
518
515
519
static bool handleTreeDependencyToolResult (
516
520
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,
518
522
SharedStream &Errs) {
519
523
if (!MaybeTree) {
520
524
llvm::handleAllErrors (
@@ -527,17 +531,15 @@ static bool handleTreeDependencyToolResult(
527
531
});
528
532
return true ;
529
533
}
530
- OS.applyLocked ([&](llvm::raw_ostream &OS) {
531
- OS << " tree " << MaybeTree->getID () << " for '" << Input << " '\n " ;
532
- });
534
+ OS << " tree " << MaybeTree->getID () << " for '" << Input << " '\n " ;
533
535
return false ;
534
536
}
535
537
536
538
static bool
537
539
handleIncludeTreeToolResult (llvm::cas::ObjectStore &CAS,
538
540
const std::string &Input,
539
541
Expected<cas::IncludeTreeRoot> &MaybeTree,
540
- SharedStream &OS, SharedStream &Errs) {
542
+ llvm::raw_ostream &OS, SharedStream &Errs) {
541
543
if (!MaybeTree) {
542
544
llvm::handleAllErrors (
543
545
MaybeTree.takeError (), [&Input, &Errs](llvm::StringError &Err) {
@@ -559,11 +561,9 @@ handleIncludeTreeToolResult(llvm::cas::ObjectStore &CAS,
559
561
};
560
562
561
563
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);
567
567
if (*E)
568
568
return printError (std::move (*E));
569
569
return false ;
@@ -682,6 +682,11 @@ class FullDeps {
682
682
}
683
683
684
684
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
+
685
690
// Sort the modules by name to get a deterministic order.
686
691
std::vector<IndexedModuleID> ModuleIDs;
687
692
for (auto &&M : Modules)
@@ -1142,8 +1147,25 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
1142
1147
});
1143
1148
1144
1149
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);
1147
1169
1148
1170
auto DiagsConsumer = std::make_unique<TextDiagnosticPrinter>(
1149
1171
llvm::errs (), new DiagnosticOptions (), false );
@@ -1361,23 +1383,23 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
1361
1383
if (Format == ScanningOutputFormat::Tree) {
1362
1384
for (auto &TreeResult : TreeResults) {
1363
1385
if (handleTreeDependencyToolResult (*CAS, TreeResult.Filename ,
1364
- *TreeResult.MaybeTree , DependencyOS,
1365
- Errs))
1386
+ *TreeResult.MaybeTree ,
1387
+ ThreadUnsafeDependencyOS, Errs))
1366
1388
HadErrors = true ;
1367
1389
}
1368
1390
} else if (Format == ScanningOutputFormat::IncludeTree) {
1369
1391
for (auto &TreeResult : TreeResults) {
1370
1392
if (handleIncludeTreeToolResult (*CAS, TreeResult.Filename ,
1371
1393
*TreeResult.MaybeIncludeTree ,
1372
- DependencyOS , Errs))
1394
+ ThreadUnsafeDependencyOS , Errs))
1373
1395
HadErrors = true ;
1374
1396
}
1375
1397
} else if (Format == ScanningOutputFormat::Full ||
1376
1398
Format == ScanningOutputFormat::FullTree ||
1377
1399
Format == ScanningOutputFormat::FullIncludeTree) {
1378
- FD->printFullOutput (llvm::outs () );
1400
+ FD->printFullOutput (ThreadUnsafeDependencyOS );
1379
1401
} else if (Format == ScanningOutputFormat::P1689)
1380
- PD.printDependencies(llvm::outs() );
1402
+ PD.printDependencies(ThreadUnsafeDependencyOS );
1381
1403
1382
1404
return HadErrors;
1383
1405
}
0 commit comments