arphaman updated this revision to Diff 205886.
arphaman marked 3 inline comments as done.
arphaman added a comment.

removed the lock


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63579/new/

https://reviews.llvm.org/D63579

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

Index: clang/tools/clang-scan-deps/ClangScanDeps.cpp
===================================================================
--- clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -29,12 +29,58 @@
 
 namespace {
 
+class DependencyCollectorFactory {
+public:
+  virtual ~DependencyCollectorFactory() {}
+
+  virtual std::shared_ptr<DependencyCollector> createDependencyCollector(
+      const std::unique_ptr<DependencyOutputOptions> Opts) = 0;
+};
+
+/// Prints out all of the gathered dependencies into one output stream instead
+/// of using the output dependency file.
+class DependencyPrinter : public DependencyFileGenerator {
+public:
+  class Factory : public DependencyCollectorFactory {
+  public:
+    Factory(raw_ostream &OS) : OS(OS) {}
+
+    std::shared_ptr<DependencyCollector> createDependencyCollector(
+        std::unique_ptr<DependencyOutputOptions> Opts) override {
+      return std::make_shared<DependencyPrinter>(std::move(Opts), SharedLock,
+                                                 OS);
+    }
+
+  private:
+    std::mutex SharedLock;
+    raw_ostream &OS;
+  };
+
+  DependencyPrinter(std::unique_ptr<DependencyOutputOptions> Opts,
+                    std::mutex &Lock, raw_ostream &OS)
+      : DependencyFileGenerator(*Opts), Opts(std::move(Opts)), Lock(Lock),
+        OS(OS) {}
+
+  void finishedMainFile(DiagnosticsEngine &Diags) override {
+    std::unique_lock<std::mutex> LockGuard(Lock);
+    outputDependencyFile(OS);
+    OS.flush();
+  }
+
+private:
+  std::unique_ptr<DependencyOutputOptions> Opts;
+  std::mutex &Lock;
+  raw_ostream &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,
+                       DependencyCollectorFactory &DepCollectorFactory)
+      : WorkingDirectory(WorkingDirectory),
+        DepCollectorFactory(DepCollectorFactory) {}
 
   bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
                      FileManager *FileMgr,
@@ -53,6 +99,21 @@
 
     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(
+        DepCollectorFactory.createDependencyCollector(std::move(Opts)));
+
     auto Action = llvm::make_unique<PreprocessOnlyAction>();
     const bool Result = Compiler.ExecuteAction(*Action);
     FileMgr->clearStatCache();
@@ -61,6 +122,7 @@
 
 private:
   StringRef WorkingDirectory;
+  DependencyCollectorFactory &DepCollectorFactory;
 };
 
 /// A proxy file system that doesn't call `chdir` when changing the working
@@ -93,8 +155,9 @@
   ///
   /// \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,
+                         DependencyCollectorFactory &DepCollectorFactory)
+      : Compilations(Compilations), DepCollectorFactory(DepCollectorFactory) {
     PCHContainerOps = std::make_shared<PCHContainerOperations>();
     BaseFS = new ProxyFileSystemWithoutChdir(llvm::vfs::getRealFileSystem());
   }
@@ -107,12 +170,13 @@
     tooling::ClangTool Tool(Compilations, Input, PCHContainerOps, BaseFS);
     Tool.clearArgumentsAdjusters();
     Tool.setRestoreWorkingDir(false);
-    PreprocessorOnlyTool Action(CWD);
+    PreprocessorOnlyTool Action(CWD, DepCollectorFactory);
     return Tool.run(&Action);
   }
 
 private:
   const tooling::CompilationDatabase &Compilations;
+  DependencyCollectorFactory &DepCollectorFactory;
   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
   /// The real filesystem used as a base for all the operations performed by the
   /// tool.
@@ -176,12 +240,14 @@
         return AdjustedArgs;
       });
 
+  // Print out the dependency results to STDOUT by default.
+  DependencyPrinter::Factory DepPrintFactory(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, DepPrintFactory));
 
   std::vector<std::thread> WorkerThreads;
   std::atomic<bool> HadErrors(false);
Index: clang/test/ClangScanDeps/regular_cdb.cpp
===================================================================
--- clang/test/ClangScanDeps/regular_cdb.cpp
+++ clang/test/ClangScanDeps/regular_cdb.cpp
@@ -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
Index: clang/test/ClangScanDeps/Inputs/regular_cdb.json
===================================================================
--- clang/test/ClangScanDeps/Inputs/regular_cdb.json
+++ clang/test/ClangScanDeps/Inputs/regular_cdb.json
@@ -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"
 }
 ]
Index: clang/lib/Frontend/DependencyFile.cpp
===================================================================
--- clang/lib/Frontend/DependencyFile.cpp
+++ clang/lib/Frontend/DependencyFile.cpp
@@ -322,6 +322,10 @@
     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
Index: clang/include/clang/Frontend/Utils.h
===================================================================
--- clang/include/clang/Frontend/Utils.h
+++ clang/include/clang/Frontend/Utils.h
@@ -132,6 +132,9 @@
   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);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to