Index: clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp =================================================================== --- clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -116,9 +116,10 @@ // and thus won't write out the extra '.d' files to disk. auto Opts = std::make_unique( std::move(Compiler.getInvocation().getDependencyOutputOpts())); + // FIXME: This is a hack. // We need at least one -MT equivalent for the generator to work. if (Opts->Targets.empty()) - Opts->Targets = {"clang-scan-deps dependency"}; + Opts->Targets = {"__THIS_IS_A_HACK__"}; Compiler.addDependencyCollector( std::make_shared(std::move(Opts), Consumer)); Index: clang/tools/clang-scan-deps/ClangScanDeps.cpp =================================================================== --- clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -11,6 +11,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" #include "clang/Tooling/JSONCompilationDatabase.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/Options.h" #include "llvm/Support/Program.h" @@ -57,8 +58,8 @@ /// /// \returns A \c StringError with the diagnostic output if clang errors /// occurred, dependency file contents otherwise. - llvm::Expected getDependencyFile(const std::string &Input, - StringRef CWD) { + llvm::Expected getDependencyFile(StringRef Input, StringRef CWD, + StringRef CompilationOutput) { /// Prints out all of the gathered dependencies into a string. class DependencyPrinterConsumer : public DependencyConsumer { public: @@ -69,10 +70,14 @@ Dependencies.push_back(File); } - void printDependencies(std::string &S) { + void printDependencies(StringRef CompilationOutput, std::string &S) { if (!Opts) return; + if (Opts->Targets.empty() || + Opts->Targets == std::vector{"__THIS_IS_A_HACK__"}) + Opts->Targets = {CompilationOutput}; + class DependencyPrinter : public DependencyFileGenerator { public: DependencyPrinter(DependencyOutputOptions &Opts, @@ -103,15 +108,17 @@ if (Result) return std::move(Result); std::string Output; - Consumer.printDependencies(Output); + + Consumer.printDependencies(CompilationOutput, Output); + return Output; } /// Computes the dependencies for the given file and prints them out. /// /// \returns True on error. - bool runOnFile(const std::string &Input, StringRef CWD) { - auto MaybeFile = getDependencyFile(Input, CWD); + bool runOnFile(StringRef Input, StringRef CWD, StringRef Output) { + auto MaybeFile = getDependencyFile(Input, CWD, Output); if (!MaybeFile) { llvm::handleAllErrors( MaybeFile.takeError(), [this, &Input](llvm::StringError &Err) { @@ -170,6 +177,19 @@ } // end anonymous namespace +static std::string getOutputFromCompilationCommandLine( + const std::vector &CommandLine) { + bool NextOneIsTheOutput = false; + for (const auto &arg : CommandLine) { + if (NextOneIsTheOutput) { + return arg; + } + NextOneIsTheOutput = (arg == "-o"); + } + // FIXME + return "a.out"; +} + int main(int argc, const char **argv) { llvm::InitLLVM X(argc, argv); llvm::cl::HideUnrelatedOptions(DependencyScannerCategory); @@ -188,10 +208,23 @@ llvm::cl::PrintOptionValues(); + // Non-owning set of strings backed by some storage. + struct DependencyScanInput { + StringRef FileName; + StringRef Directory; + std::string Output; + }; + // By default the tool runs on all inputs in the CDB. - std::vector> Inputs; - for (const auto &Command : Compilations->getAllCompileCommands()) - Inputs.emplace_back(Command.Filename, Command.Directory); + auto CompilationComands = Compilations->getAllCompileCommands(); + std::vector Inputs; + for (const auto &Command : CompilationComands) { + Inputs.push_back( + {Command.Filename, Command.Directory, + Command.Output.empty() + ? getOutputFromCompilationCommandLine(Command.CommandLine) + : Command.Output}); + } // The command options are rewritten to run Clang in preprocessor only mode. auto AdjustingCompilations = @@ -235,20 +268,21 @@ << " files using " << NumWorkers << " workers\n"; for (unsigned I = 0; I < NumWorkers; ++I) { auto Worker = [I, &Lock, &Index, &Inputs, &HadErrors, &WorkerTools]() { + size_t IndexToProcess = 0; while (true) { - std::string Input; - StringRef CWD; // Take the next input. { std::unique_lock LockGuard(Lock); - if (Index >= Inputs.size()) - return; - const auto &Compilation = Inputs[Index++]; - Input = Compilation.first; - CWD = Compilation.second; + IndexToProcess = Index++; } + if (IndexToProcess >= Inputs.size()) + return; + + const auto &Compilation = Inputs[IndexToProcess]; // Run the tool on it. - if (WorkerTools[I]->runOnFile(Input, CWD)) + if (WorkerTools[I]->runOnFile(Compilation.FileName, + Compilation.Directory, + Compilation.Output)) HadErrors = true; } };