@@ -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;
@@ -115,8 +116,8 @@ static bool RoundTripArgs = DoRoundTripDefault;
115
116
static void ParseArgs (int argc, char **argv) {
116
117
ScanDepsOptTable Tbl;
117
118
llvm::StringRef ToolName = argv[0 ];
118
- llvm::BumpPtrAllocator A ;
119
- llvm::StringSaver Saver{A };
119
+ llvm::BumpPtrAllocator Alloc ;
120
+ llvm::StringSaver Saver{Alloc };
120
121
llvm::opt::InputArgList Args =
121
122
Tbl.parseArgs (argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
122
123
llvm::errs () << Msg << ' \n ' ;
@@ -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)) {
@@ -207,14 +211,8 @@ static void ParseArgs(int argc, char **argv) {
207
211
}
208
212
}
209
213
210
- if (const llvm::opt::Arg *A = Args.getLastArg (OPT_compilation_database_EQ)) {
214
+ if (const llvm::opt::Arg *A = Args.getLastArg (OPT_compilation_database_EQ))
211
215
CompilationDB = A->getValue ();
212
- } else if (Format != ScanningOutputFormat::P1689) {
213
- llvm::errs () << ToolName
214
- << " : for the --compiilation-database option: must be "
215
- " specified at least once!" ;
216
- std::exit (1 );
217
- }
218
216
219
217
if (const llvm::opt::Arg *A = Args.getLastArg (OPT_module_name_EQ))
220
218
ModuleName = A->getValue ();
@@ -265,9 +263,8 @@ static void ParseArgs(int argc, char **argv) {
265
263
266
264
RoundTripArgs = Args.hasArg (OPT_round_trip_args);
267
265
268
- if (auto *A = Args.getLastArgNoClaim (OPT_DASH_DASH))
269
- CommandLine.insert (CommandLine.end (), A->getValues ().begin (),
270
- A->getValues ().end ());
266
+ if (const llvm::opt::Arg *A = Args.getLastArgNoClaim (OPT_DASH_DASH))
267
+ CommandLine.assign (A->getValues ().begin (), A->getValues ().end ());
271
268
}
272
269
273
270
class SharedStream {
@@ -521,7 +518,7 @@ handleMakeDependencyToolResult(const std::string &Input,
521
518
522
519
static bool handleTreeDependencyToolResult (
523
520
llvm::cas::ObjectStore &CAS, const std::string &Input,
524
- llvm::Expected<llvm::cas::ObjectProxy> &MaybeTree, SharedStream &OS,
521
+ llvm::Expected<llvm::cas::ObjectProxy> &MaybeTree, llvm::raw_ostream &OS,
525
522
SharedStream &Errs) {
526
523
if (!MaybeTree) {
527
524
llvm::handleAllErrors (
@@ -534,17 +531,15 @@ static bool handleTreeDependencyToolResult(
534
531
});
535
532
return true ;
536
533
}
537
- OS.applyLocked ([&](llvm::raw_ostream &OS) {
538
- OS << " tree " << MaybeTree->getID () << " for '" << Input << " '\n " ;
539
- });
534
+ OS << " tree " << MaybeTree->getID () << " for '" << Input << " '\n " ;
540
535
return false ;
541
536
}
542
537
543
538
static bool
544
539
handleIncludeTreeToolResult (llvm::cas::ObjectStore &CAS,
545
540
const std::string &Input,
546
541
Expected<cas::IncludeTreeRoot> &MaybeTree,
547
- SharedStream &OS, SharedStream &Errs) {
542
+ llvm::raw_ostream &OS, SharedStream &Errs) {
548
543
if (!MaybeTree) {
549
544
llvm::handleAllErrors (
550
545
MaybeTree.takeError (), [&Input, &Errs](llvm::StringError &Err) {
@@ -566,11 +561,9 @@ handleIncludeTreeToolResult(llvm::cas::ObjectStore &CAS,
566
561
};
567
562
568
563
std::optional<llvm::Error> E;
569
- OS.applyLocked ([&](llvm::raw_ostream &OS) {
570
- MaybeTree->getID ().print (OS);
571
- OS << " - " << Input << " \n " ;
572
- E = MaybeTree->print (OS);
573
- });
564
+ MaybeTree->getID ().print (OS);
565
+ OS << " - " << Input << " \n " ;
566
+ E = MaybeTree->print (OS);
574
567
if (*E)
575
568
return printError (std::move (*E));
576
569
return false ;
@@ -689,6 +682,11 @@ class FullDeps {
689
682
}
690
683
691
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
+
692
690
// Sort the modules by name to get a deterministic order.
693
691
std::vector<IndexedModuleID> ModuleIDs;
694
692
for (auto &&M : Modules)
@@ -975,39 +973,29 @@ static std::string getModuleCachePath(ArrayRef<std::string> Args) {
975
973
return std::string (Path);
976
974
}
977
975
978
- // getCompilationDataBase - If -compilation-database is set, load the
979
- // compilation database from the specified file. Otherwise if the we're
980
- // generating P1689 format, trying to generate the compilation database
981
- // form specified command line after the positional parameter "--".
976
+ // / Attempts to construct the compilation database from '-compilation-database'
977
+ // / or from the arguments following the positional '--'.
982
978
static std::unique_ptr<tooling::CompilationDatabase>
983
- getCompilationDataBase (int argc, char **argv, std::string &ErrorMessage) {
979
+ getCompilationDatabase (int argc, char **argv, std::string &ErrorMessage) {
984
980
llvm::InitLLVM X (argc, argv);
985
981
ParseArgs (argc, argv);
986
982
983
+ if (!(CommandLine.empty () ^ CompilationDB.empty ())) {
984
+ llvm::errs () << " The compilation command line must be provided either via "
985
+ " '-compilation-database' or after '--'." ;
986
+ return nullptr ;
987
+ }
988
+
987
989
if (!CompilationDB.empty ())
988
990
return tooling::JSONCompilationDatabase::loadFromFile (
989
991
CompilationDB, ErrorMessage,
990
992
tooling::JSONCommandLineSyntax::AutoDetect);
991
993
992
- if (Format != ScanningOutputFormat::P1689) {
993
- llvm::errs () << " the --compilation-database option: must be specified at "
994
- " least once!" ;
995
- return nullptr ;
996
- }
997
-
998
- // Trying to get the input file, the output file and the command line options
999
- // from the positional parameter "--".
1000
- char **DoubleDash = std::find (argv, argv + argc, StringRef (" --" ));
1001
- if (DoubleDash == argv + argc) {
1002
- llvm::errs () << " The command line arguments is required after '--' in "
1003
- " P1689 per file mode." ;
1004
- return nullptr ;
1005
- }
1006
-
1007
994
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
1008
995
CompilerInstance::createDiagnostics (new DiagnosticOptions);
1009
996
driver::Driver TheDriver (CommandLine[0 ], llvm::sys::getDefaultTargetTriple (),
1010
997
*Diags);
998
+ TheDriver.setCheckInputsExist (false );
1011
999
std::unique_ptr<driver::Compilation> C (
1012
1000
TheDriver.BuildCompilation (CommandLine));
1013
1001
if (!C)
@@ -1022,7 +1010,8 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
1022
1010
1023
1011
FrontendOptions &FEOpts = CI->getFrontendOpts ();
1024
1012
if (FEOpts.Inputs .size () != 1 ) {
1025
- llvm::errs () << " Only one input file is allowed in P1689 per file mode." ;
1013
+ llvm::errs ()
1014
+ << " Exactly one input file is required in the per-file mode ('--').\n " ;
1026
1015
return nullptr ;
1027
1016
}
1028
1017
@@ -1031,8 +1020,9 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
1031
1020
auto LastCmd = C->getJobs ().end ();
1032
1021
LastCmd--;
1033
1022
if (LastCmd->getOutputFilenames ().size () != 1 ) {
1034
- llvm::errs () << " The command line should provide exactly one output file "
1035
- " in P1689 per file mode.\n " ;
1023
+ llvm::errs ()
1024
+ << " Exactly one output file is required in the per-file mode ('--').\n " ;
1025
+ return nullptr ;
1036
1026
}
1037
1027
StringRef OutputFile = LastCmd->getOutputFilenames ().front ();
1038
1028
@@ -1072,7 +1062,7 @@ getCompilationDataBase(int argc, char **argv, std::string &ErrorMessage) {
1072
1062
int clang_scan_deps_main (int argc, char **argv, const llvm::ToolContext &) {
1073
1063
std::string ErrorMessage;
1074
1064
std::unique_ptr<tooling::CompilationDatabase> Compilations =
1075
- getCompilationDataBase (argc, argv, ErrorMessage);
1065
+ getCompilationDatabase (argc, argv, ErrorMessage);
1076
1066
if (!Compilations) {
1077
1067
llvm::errs () << ErrorMessage << " \n " ;
1078
1068
return 1 ;
@@ -1157,8 +1147,25 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
1157
1147
});
1158
1148
1159
1149
SharedStream Errs (llvm::errs ());
1160
- // Print out the dependency results to STDOUT by default.
1161
- 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);
1162
1169
1163
1170
auto DiagsConsumer = std::make_unique<TextDiagnosticPrinter>(
1164
1171
llvm::errs (), new DiagnosticOptions (), false );
@@ -1376,23 +1383,23 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
1376
1383
if (Format == ScanningOutputFormat::Tree) {
1377
1384
for (auto &TreeResult : TreeResults) {
1378
1385
if (handleTreeDependencyToolResult (*CAS, TreeResult.Filename ,
1379
- *TreeResult.MaybeTree , DependencyOS,
1380
- Errs))
1386
+ *TreeResult.MaybeTree ,
1387
+ ThreadUnsafeDependencyOS, Errs))
1381
1388
HadErrors = true ;
1382
1389
}
1383
1390
} else if (Format == ScanningOutputFormat::IncludeTree) {
1384
1391
for (auto &TreeResult : TreeResults) {
1385
1392
if (handleIncludeTreeToolResult (*CAS, TreeResult.Filename ,
1386
1393
*TreeResult.MaybeIncludeTree ,
1387
- DependencyOS , Errs))
1394
+ ThreadUnsafeDependencyOS , Errs))
1388
1395
HadErrors = true ;
1389
1396
}
1390
1397
} else if (Format == ScanningOutputFormat::Full ||
1391
1398
Format == ScanningOutputFormat::FullTree ||
1392
1399
Format == ScanningOutputFormat::FullIncludeTree) {
1393
- FD->printFullOutput (llvm::outs () );
1400
+ FD->printFullOutput (ThreadUnsafeDependencyOS );
1394
1401
} else if (Format == ScanningOutputFormat::P1689)
1395
- PD.printDependencies(llvm::outs() );
1402
+ PD.printDependencies(ThreadUnsafeDependencyOS );
1396
1403
1397
1404
return HadErrors;
1398
1405
}
0 commit comments