r364088 - [clang-scan-deps] print the dependencies to stdout

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 21 11:24:55 PDT 2019


Author: arphaman
Date: Fri Jun 21 11:24:55 2019
New Revision: 364088

URL: http://llvm.org/viewvc/llvm-project?rev=364088&view=rev
Log:
[clang-scan-deps] print the dependencies to stdout
and remove the need to use -MD options in the CDB

Differential Revision: https://reviews.llvm.org/D63579

Modified:
    cfe/trunk/include/clang/Frontend/Utils.h
    cfe/trunk/lib/Frontend/DependencyFile.cpp
    cfe/trunk/test/ClangScanDeps/Inputs/regular_cdb.json
    cfe/trunk/test/ClangScanDeps/regular_cdb.cpp
    cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp

Modified: cfe/trunk/include/clang/Frontend/Utils.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/Utils.h?rev=364088&r1=364087&r2=364088&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/Utils.h (original)
+++ cfe/trunk/include/clang/Frontend/Utils.h Fri Jun 21 11:24:55 2019
@@ -132,6 +132,9 @@ public:
   bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem,
                      bool IsModuleFile, bool IsMissing) final override;
 
+protected:
+  void outputDependencyFile(llvm::raw_ostream &OS);
+
 private:
   void outputDependencyFile(DiagnosticsEngine &Diags);
 

Modified: cfe/trunk/lib/Frontend/DependencyFile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DependencyFile.cpp?rev=364088&r1=364087&r2=364088&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/DependencyFile.cpp (original)
+++ cfe/trunk/lib/Frontend/DependencyFile.cpp Fri Jun 21 11:24:55 2019
@@ -322,6 +322,10 @@ void DependencyFileGenerator::outputDepe
     return;
   }
 
+  outputDependencyFile(OS);
+}
+
+void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) {
   // Write out the dependency targets, trying to avoid overly long
   // lines when possible. We try our best to emit exactly the same
   // dependency file as GCC (4.2), assuming the included files are the

Modified: cfe/trunk/test/ClangScanDeps/Inputs/regular_cdb.json
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ClangScanDeps/Inputs/regular_cdb.json?rev=364088&r1=364087&r2=364088&view=diff
==============================================================================
--- cfe/trunk/test/ClangScanDeps/Inputs/regular_cdb.json (original)
+++ cfe/trunk/test/ClangScanDeps/Inputs/regular_cdb.json Fri Jun 21 11:24:55 2019
@@ -1,12 +1,12 @@
 [
 {
   "directory": "DIR",
-  "command": "clang -E -fsyntax-only DIR/regular_cdb.cpp -IInputs -MD -MF DIR/regular_cdb.d",
-  "file": "DIR/regular_cdb.cpp"
+  "command": "clang -E -fsyntax-only DIR/regular_cdb2.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/regular_cdb2.d",
+  "file": "DIR/regular_cdb2.cpp"
 },
 {
   "directory": "DIR",
-  "command": "clang -E -fsyntax-only DIR/regular_cdb.cpp -IInputs -D INCLUDE_HEADER2 -MD -MF DIR/regular_cdb2.d",
+  "command": "clang -E -fsyntax-only DIR/regular_cdb.cpp -IInputs",
   "file": "DIR/regular_cdb.cpp"
 }
 ]

Modified: cfe/trunk/test/ClangScanDeps/regular_cdb.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ClangScanDeps/regular_cdb.cpp?rev=364088&r1=364087&r2=364088&view=diff
==============================================================================
--- cfe/trunk/test/ClangScanDeps/regular_cdb.cpp (original)
+++ cfe/trunk/test/ClangScanDeps/regular_cdb.cpp Fri Jun 21 11:24:55 2019
@@ -2,26 +2,35 @@
 // RUN: rm -rf %t.cdb
 // RUN: mkdir -p %t.dir
 // RUN: cp %s %t.dir/regular_cdb.cpp
+// RUN: cp %s %t.dir/regular_cdb2.cpp
 // RUN: mkdir %t.dir/Inputs
 // RUN: cp %S/Inputs/header.h %t.dir/Inputs/header.h
 // RUN: cp %S/Inputs/header2.h %t.dir/Inputs/header2.h
 // RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/regular_cdb.json > %t.cdb
 //
-// RUN: clang-scan-deps -compilation-database %t.cdb -j 1
-// RUN: cat %t.dir/regular_cdb.d | FileCheck %s
-// RUN: cat %t.dir/regular_cdb2.d | FileCheck --check-prefix=CHECK2 %s
-// RUN: rm -rf %t.dir/regular_cdb.d %t.dir/regular_cdb2.d
+// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 | \
+// RUN:   FileCheck --check-prefixes=CHECK1,CHECK2,CHECK2NO %s
 //
-// RUN: clang-scan-deps -compilation-database %t.cdb -j 2
-// RUN: cat %t.dir/regular_cdb.d | FileCheck %s
-// RUN: cat %t.dir/regular_cdb2.d | FileCheck --check-prefix=CHECK2 %s
+// Make sure we didn't produce any dependency files!
+// RUN: not cat %t.dir/regular_cdb.d
+// RUN: not cat %t.dir/regular_cdb2.d
+//
+// The output order is non-deterministic when using more than one thread,
+// so check the output using two runs. Note that the 'NOT' check is not used
+// as it might fail if the results for `regular_cdb.cpp` are reported before
+// `regular_cdb2.cpp`.
+//
+// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 | \
+// RUN:   FileCheck --check-prefix=CHECK1 %s
+// RUN: clang-scan-deps -compilation-database %t.cdb -j 2 | \
+// RUN:   FileCheck --check-prefix=CHECK2 %s
 
 #include "header.h"
 
-// CHECK: regular_cdb.cpp
-// CHECK-NEXT: Inputs{{/|\\}}header.h
-// CHECK-NOT: header2
+// CHECK1: regular_cdb2.cpp
+// CHECK1-NEXT: Inputs{{/|\\}}header.h
+// CHECK1-NEXT: Inputs{{/|\\}}header2.h
 
 // CHECK2: regular_cdb.cpp
 // CHECK2-NEXT: Inputs{{/|\\}}header.h
-// CHECK2-NEXT: Inputs{{/|\\}}header2.h
+// CHECK2NO-NOT: header2

Modified: cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp?rev=364088&r1=364087&r2=364088&view=diff
==============================================================================
--- cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp (original)
+++ cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp Fri Jun 21 11:24:55 2019
@@ -29,12 +29,43 @@ using namespace clang;
 
 namespace {
 
+class SharedStream {
+public:
+  SharedStream(raw_ostream &OS) : OS(OS) {}
+  void applyLocked(llvm::function_ref<void(raw_ostream &OS)> Fn) {
+    std::unique_lock<std::mutex> LockGuard(Lock);
+    Fn(OS);
+    OS.flush();
+  }
+
+private:
+  std::mutex Lock;
+  raw_ostream &OS;
+};
+
+/// Prints out all of the gathered dependencies into one output stream instead
+/// of using the output dependency file.
+class DependencyPrinter : public DependencyFileGenerator {
+public:
+  DependencyPrinter(std::unique_ptr<DependencyOutputOptions> Opts,
+                    SharedStream &OS)
+      : DependencyFileGenerator(*Opts), Opts(std::move(Opts)), OS(OS) {}
+
+  void finishedMainFile(DiagnosticsEngine &Diags) override {
+    OS.applyLocked([this](raw_ostream &OS) { outputDependencyFile(OS); });
+  }
+
+private:
+  std::unique_ptr<DependencyOutputOptions> Opts;
+  SharedStream &OS;
+};
+
 /// A clang tool that runs the preprocessor only for the given compiler
 /// invocation.
 class PreprocessorOnlyTool : public tooling::ToolAction {
 public:
-  PreprocessorOnlyTool(StringRef WorkingDirectory)
-      : WorkingDirectory(WorkingDirectory) {}
+  PreprocessorOnlyTool(StringRef WorkingDirectory, SharedStream &OS)
+      : WorkingDirectory(WorkingDirectory), OS(OS) {}
 
   bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
                      FileManager *FileMgr,
@@ -53,6 +84,21 @@ public:
 
     Compiler.createSourceManager(*FileMgr);
 
+    // Create the dependency collector that will collect the produced
+    // dependencies.
+    //
+    // This also moves the existing dependency output options from the
+    // invocation to the collector. The options in the invocation are reset,
+    // which ensures that the compiler won't create new dependency collectors,
+    // and thus won't write out the extra '.d' files to disk.
+    auto Opts = llvm::make_unique<DependencyOutputOptions>(
+        std::move(Compiler.getInvocation().getDependencyOutputOpts()));
+    // We need at least one -MT equivalent for the generator to work.
+    if (Opts->Targets.empty())
+      Opts->Targets = {"clang-scan-deps dependency"};
+    Compiler.addDependencyCollector(
+        std::make_shared<DependencyPrinter>(std::move(Opts), OS));
+
     auto Action = llvm::make_unique<PreprocessOnlyAction>();
     const bool Result = Compiler.ExecuteAction(*Action);
     FileMgr->clearStatCache();
@@ -61,6 +107,7 @@ public:
 
 private:
   StringRef WorkingDirectory;
+  SharedStream &OS;
 };
 
 /// A proxy file system that doesn't call `chdir` when changing the working
@@ -93,8 +140,9 @@ public:
   ///
   /// \param Compilations     The reference to the compilation database that's
   /// used by the clang tool.
-  DependencyScanningTool(const tooling::CompilationDatabase &Compilations)
-      : Compilations(Compilations) {
+  DependencyScanningTool(const tooling::CompilationDatabase &Compilations,
+                         SharedStream &OS)
+      : Compilations(Compilations), OS(OS) {
     PCHContainerOps = std::make_shared<PCHContainerOperations>();
     BaseFS = new ProxyFileSystemWithoutChdir(llvm::vfs::getRealFileSystem());
   }
@@ -107,12 +155,13 @@ public:
     tooling::ClangTool Tool(Compilations, Input, PCHContainerOps, BaseFS);
     Tool.clearArgumentsAdjusters();
     Tool.setRestoreWorkingDir(false);
-    PreprocessorOnlyTool Action(CWD);
+    PreprocessorOnlyTool Action(CWD, OS);
     return Tool.run(&Action);
   }
 
 private:
   const tooling::CompilationDatabase &Compilations;
+  SharedStream &OS;
   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
   /// The real filesystem used as a base for all the operations performed by the
   /// tool.
@@ -176,12 +225,14 @@ int main(int argc, const char **argv) {
         return AdjustedArgs;
       });
 
+  // Print out the dependency results to STDOUT by default.
+  SharedStream DependencyOS(llvm::outs());
   unsigned NumWorkers =
       NumThreads == 0 ? llvm::hardware_concurrency() : NumThreads;
   std::vector<std::unique_ptr<DependencyScanningTool>> WorkerTools;
   for (unsigned I = 0; I < NumWorkers; ++I)
-    WorkerTools.push_back(
-        llvm::make_unique<DependencyScanningTool>(*AdjustingCompilations));
+    WorkerTools.push_back(llvm::make_unique<DependencyScanningTool>(
+        *AdjustingCompilations, DependencyOS));
 
   std::vector<std::thread> WorkerThreads;
   std::atomic<bool> HadErrors(false);




More information about the cfe-commits mailing list