diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -62,6 +62,26 @@ std::map &PrebuiltModuleFiles; }; +/// Transform arbitrary file name into an object-like file name. +static std::string makeObjFileName(StringRef FileName) { + SmallString<128> ObjFileName(FileName); + llvm::sys::path::replace_extension(ObjFileName, "o"); + return std::string(ObjFileName.str()); +} + +/// Deduce the dependency target based on the output file and input files. +static std::string +deduceDepTarget(const std::string &OutputFile, + const SmallVectorImpl &InputFiles) { + if (OutputFile != "-") + return OutputFile; + + if (InputFiles.empty() || !InputFiles.front().isFile()) + return "clang-scan-deps\\ dependency"; + + return makeObjFileName(InputFiles.front().getFile()); +} + /// A clang tool that runs the preprocessor in a mode that's optimized for /// dependency scanning for the given compiler invocation. class DependencyScanningAction : public tooling::ToolAction { @@ -150,9 +170,11 @@ // and thus won't write out the extra '.d' files to disk. auto Opts = std::make_unique( std::move(Compiler.getInvocation().getDependencyOutputOpts())); - // We need at least one -MT equivalent for the generator to work. + // We need at least one -MT equivalent for the generator of make dependency + // files to work. if (Opts->Targets.empty()) - Opts->Targets = {"clang-scan-deps dependency"}; + Opts->Targets = {deduceDepTarget(Compiler.getFrontendOpts().OutputFile, + Compiler.getFrontendOpts().Inputs)}; switch (Format) { case ScanningOutputFormat::Make: diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c --- a/clang/test/ClangScanDeps/modules-pch.c +++ b/clang/test/ClangScanDeps/modules-pch.c @@ -9,6 +9,9 @@ // RUN: -generate-modules-path-args -module-files-dir %t/build -mode preprocess >> %t/result_pch.json // RUN: cat %t/result_pch.json | sed 's:\\\\\?:/:g' | FileCheck %s -check-prefix=CHECK-PCH // +// Check we didn't build the PCH during dependency scanning. +// RUN: not cat %/t/pch.h.gch +// // CHECK-PCH: -[[PREFIX:.*]] // CHECK-PCH-NEXT: { // CHECK-PCH-NEXT: "modules": [ diff --git a/clang/test/ClangScanDeps/modules.cpp b/clang/test/ClangScanDeps/modules.cpp --- a/clang/test/ClangScanDeps/modules.cpp +++ b/clang/test/ClangScanDeps/modules.cpp @@ -42,13 +42,14 @@ #include "header.h" -// CHECK1: modules_cdb_input2.cpp +// CHECK1: modules_cdb_input2.o: // CHECK1-NEXT: modules_cdb_input2.cpp // CHECK1-NEXT: Inputs{{/|\\}}module.modulemap // CHECK1-NEXT: Inputs{{/|\\}}header2.h // CHECK1: Inputs{{/|\\}}header.h -// CHECK2: modules_cdb_input.cpp +// CHECK2: {{.*}}.o: +// CHECK2-NEXT: modules_cdb_input.cpp // CHECK2-NEXT: Inputs{{/|\\}}module.modulemap // CHECK2-NEXT: Inputs{{/|\\}}header.h // CHECK2NO-NOT: header2 diff --git a/clang/test/ClangScanDeps/regular_cdb.cpp b/clang/test/ClangScanDeps/regular_cdb.cpp --- a/clang/test/ClangScanDeps/regular_cdb.cpp +++ b/clang/test/ClangScanDeps/regular_cdb.cpp @@ -58,14 +58,14 @@ #include "header.h" -// CHECK1: regular_cdb_input2.cpp +// CHECK1: regular_cdb_input2.o: // CHECK1-NEXT: regular_cdb_input2.cpp // CHECK1-NEXT: Inputs{{/|\\}}header.h // CHECK1-NEXT: Inputs{{/|\\}}header2.h -// CHECK3: regular_cdb_input.o -// CHECK2: regular_cdb_input.cpp +// CHECK2: regular_cdb_input.o: +// CHECK2-NEXT: regular_cdb_input.cpp // CHECK2-NEXT: Inputs{{/|\\}}header.h // CHECK2NO-NOT: header2 -// CHECK3: adena.o +// CHECK3: adena.o: diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -201,13 +201,6 @@ } // end anonymous namespace -/// \returns object-file path derived from source-file path. -static std::string getObjFilePath(StringRef SrcFile) { - SmallString<128> ObjFileName(SrcFile); - llvm::sys::path::replace_extension(ObjFileName, "o"); - return std::string(ObjFileName.str()); -} - class SingleCommandCompilationDatabase : public tooling::CompilationDatabase { public: SingleCommandCompilationDatabase(tooling::CompileCommand Cmd) @@ -463,16 +456,10 @@ std::move(Compilations)); ResourceDirectoryCache ResourceDirCache; - // FIXME: Adjust the resulting CompilerInvocation in DependencyScanningAction - // instead of parsing and adjusting the raw command-line. This will make it - // possible to remove some code specific to clang-cl and Windows. AdjustingCompilations->appendArgumentsAdjuster( [&ResourceDirCache](const tooling::CommandLineArguments &Args, StringRef FileName) { std::string LastO = ""; - bool HasMT = false; - bool HasMQ = false; - bool HasMD = false; bool HasResourceDir = false; bool ClangCLMode = false; auto FlagsEnd = llvm::find(Args, "--"); @@ -503,58 +490,17 @@ if (!LastO.empty() && !llvm::sys::path::has_extension(LastO)) LastO.append(".obj"); } - if (Arg == "/clang:-MT") - HasMT = true; - if (Arg == "/clang:-MQ") - HasMQ = true; - if (Arg == "/clang:-MD") - HasMD = true; - } else { - if (LastO.empty()) { - if (Arg == "-o" && I != R) - LastO = I[-1]; // Next argument (reverse iterator) - else if (Arg.startswith("-o")) - LastO = Arg.drop_front(2).str(); - } - if (Arg == "-MT") - HasMT = true; - if (Arg == "-MQ") - HasMQ = true; - if (Arg == "-MD") - HasMD = true; } if (Arg == "-resource-dir") HasResourceDir = true; } } - // If there's no -MT/-MQ Driver would add -MT with the value of the last - // -o option. tooling::CommandLineArguments AdjustedArgs(Args.begin(), FlagsEnd); - AdjustedArgs.push_back("-o"); -#ifdef _WIN32 - AdjustedArgs.push_back("nul"); -#else - AdjustedArgs.push_back("/dev/null"); -#endif - if (!HasMT && !HasMQ && Format == ScanningOutputFormat::Make) { - // We're interested in source dependencies of an object file. - std::string FileNameArg; - if (!HasMD) { - // FIXME: We are missing the directory unless the -o value is an - // absolute path. - FileNameArg = !LastO.empty() ? LastO : getObjFilePath(FileName); - } else { - FileNameArg = std::string(FileName); - } - if (ClangCLMode) { - AdjustedArgs.push_back("/clang:-M"); - AdjustedArgs.push_back("/clang:-MT"); - AdjustedArgs.push_back(Twine("/clang:", FileNameArg).str()); - } else { - AdjustedArgs.push_back("-M"); - AdjustedArgs.push_back("-MT"); - AdjustedArgs.push_back(std::move(FileNameArg)); - } + // The clang-cl driver passes "-o -" to the frontend. Inject the real + // file here to ensure "-MT" can be deduced if need be. + if (ClangCLMode && !LastO.empty()) { + AdjustedArgs.push_back("/clang:-o"); + AdjustedArgs.push_back("/clang:" + LastO); } AdjustedArgs.push_back("-Xclang"); AdjustedArgs.push_back("-sys-header-deps");