r370425 - [clang-scan-deps] NFC, refactor the DependencyScanningWorker to use a consumer

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 29 18:25:57 PDT 2019


Author: arphaman
Date: Thu Aug 29 18:25:57 2019
New Revision: 370425

URL: http://llvm.org/viewvc/llvm-project?rev=370425&view=rev
Log:
[clang-scan-deps] NFC, refactor the DependencyScanningWorker to use a consumer
to report the dependencies to the client

This will allow the scanner to report modular dependencies to the consumer.
This will also allow the scanner to accept regular cc1 clang invocations, e.g.
in an implementation of a libclang C API for clang-scan-deps, that I will add
follow-up patches for in the future.

Modified:
    cfe/trunk/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
    cfe/trunk/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
    cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp

Modified: cfe/trunk/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h?rev=370425&r1=370424&r2=370425&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h (original)
+++ cfe/trunk/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h Thu Aug 29 18:25:57 2019
@@ -19,12 +19,25 @@
 #include <string>
 
 namespace clang {
+
+class DependencyOutputOptions;
+
 namespace tooling {
 namespace dependencies {
 
 class DependencyScanningService;
 class DependencyScanningWorkerFilesystem;
 
+class DependencyConsumer {
+public:
+  virtual ~DependencyConsumer() {}
+
+  virtual void handleFileDependency(const DependencyOutputOptions &Opts,
+                                    StringRef Filename) = 0;
+
+  // FIXME: Add support for reporting modular dependencies.
+};
+
 /// An individual dependency scanning worker that is able to run on its own
 /// thread.
 ///
@@ -35,15 +48,16 @@ class DependencyScanningWorker {
 public:
   DependencyScanningWorker(DependencyScanningService &Service);
 
-  /// Print out the dependency information into a string using the dependency
-  /// file format that is specified in the options (-MD is the default) and
-  /// return it.
+  /// Run the dependency scanning tool for a given clang driver invocation (as
+  /// specified for the given Input in the CDB), and report the discovered
+  /// dependencies to the provided consumer.
   ///
   /// \returns A \c StringError with the diagnostic output if clang errors
-  /// occurred, dependency file contents otherwise.
-  llvm::Expected<std::string> getDependencyFile(const std::string &Input,
-                                                StringRef WorkingDirectory,
-                                                const CompilationDatabase &CDB);
+  /// occurred, success otherwise.
+  llvm::Error computeDependencies(const std::string &Input,
+                                  StringRef WorkingDirectory,
+                                  const CompilationDatabase &CDB,
+                                  DependencyConsumer &Consumer);
 
 private:
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;

Modified: cfe/trunk/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp?rev=370425&r1=370424&r2=370425&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp (original)
+++ cfe/trunk/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp Thu Aug 29 18:25:57 2019
@@ -21,21 +21,21 @@ using namespace dependencies;
 
 namespace {
 
-/// Prints out all of the gathered dependencies into a string.
-class DependencyPrinter : public DependencyFileGenerator {
+/// Forwards the gatherered dependencies to the consumer.
+class DependencyConsumerForwarder : public DependencyFileGenerator {
 public:
-  DependencyPrinter(std::unique_ptr<DependencyOutputOptions> Opts,
-                    std::string &S)
-      : DependencyFileGenerator(*Opts), Opts(std::move(Opts)), S(S) {}
+  DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts,
+                              DependencyConsumer &C)
+      : DependencyFileGenerator(*Opts), Opts(std::move(Opts)), C(C) {}
 
   void finishedMainFile(DiagnosticsEngine &Diags) override {
-    llvm::raw_string_ostream OS(S);
-    outputDependencyFile(OS);
+    for (const auto &File : getDependencies())
+      C.handleFileDependency(*Opts, File);
   }
 
 private:
   std::unique_ptr<DependencyOutputOptions> Opts;
-  std::string &S;
+  DependencyConsumer &C;
 };
 
 /// A proxy file system that doesn't call `chdir` when changing the working
@@ -65,10 +65,9 @@ private:
 class DependencyScanningAction : public tooling::ToolAction {
 public:
   DependencyScanningAction(
-      StringRef WorkingDirectory, std::string &DependencyFileContents,
+      StringRef WorkingDirectory, DependencyConsumer &Consumer,
       llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS)
-      : WorkingDirectory(WorkingDirectory),
-        DependencyFileContents(DependencyFileContents),
+      : WorkingDirectory(WorkingDirectory), Consumer(Consumer),
         DepFS(std::move(DepFS)) {}
 
   bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
@@ -121,8 +120,9 @@ public:
     // 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), DependencyFileContents));
+    Compiler.addDependencyCollector(
+        std::make_shared<DependencyConsumerForwarder>(std::move(Opts),
+                                                      Consumer));
 
     auto Action = std::make_unique<PreprocessOnlyAction>();
     const bool Result = Compiler.ExecuteAction(*Action);
@@ -133,8 +133,7 @@ public:
 
 private:
   StringRef WorkingDirectory;
-  /// The dependency file will be written to this string.
-  std::string &DependencyFileContents;
+  DependencyConsumer &Consumer;
   llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
 };
 
@@ -152,30 +151,35 @@ DependencyScanningWorker::DependencyScan
     Files = new FileManager(FileSystemOptions(), RealFS);
 }
 
-llvm::Expected<std::string>
-DependencyScanningWorker::getDependencyFile(const std::string &Input,
-                                            StringRef WorkingDirectory,
-                                            const CompilationDatabase &CDB) {
+static llvm::Error runWithDiags(
+    DiagnosticOptions *DiagOpts,
+    llvm::function_ref<bool(DiagnosticConsumer &DC)> BodyShouldSucceed) {
   // Capture the emitted diagnostics and report them to the client
   // in the case of a failure.
   std::string DiagnosticOutput;
   llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
-  TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, DiagOpts.get());
+  TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, DiagOpts);
 
+  if (BodyShouldSucceed(DiagPrinter))
+    return llvm::Error::success();
+  return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
+                                             llvm::inconvertibleErrorCode());
+}
+
+llvm::Error DependencyScanningWorker::computeDependencies(
+    const std::string &Input, StringRef WorkingDirectory,
+    const CompilationDatabase &CDB, DependencyConsumer &Consumer) {
   RealFS->setCurrentWorkingDirectory(WorkingDirectory);
-  /// Create the tool that uses the underlying file system to ensure that any
-  /// file system requests that are made by the driver do not go through the
-  /// dependency scanning filesystem.
-  tooling::ClangTool Tool(CDB, Input, PCHContainerOps, RealFS, Files);
-  Tool.clearArgumentsAdjusters();
-  Tool.setRestoreWorkingDir(false);
-  Tool.setPrintErrorMessage(false);
-  Tool.setDiagnosticConsumer(&DiagPrinter);
-  std::string Output;
-  DependencyScanningAction Action(WorkingDirectory, Output, DepFS);
-  if (Tool.run(&Action)) {
-    return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
-                                               llvm::inconvertibleErrorCode());
-  }
-  return Output;
+  return runWithDiags(DiagOpts.get(), [&](DiagnosticConsumer &DC) {
+    /// Create the tool that uses the underlying file system to ensure that any
+    /// file system requests that are made by the driver do not go through the
+    /// dependency scanning filesystem.
+    tooling::ClangTool Tool(CDB, Input, PCHContainerOps, RealFS, Files);
+    Tool.clearArgumentsAdjusters();
+    Tool.setRestoreWorkingDir(false);
+    Tool.setPrintErrorMessage(false);
+    Tool.setDiagnosticConsumer(&DC);
+    DependencyScanningAction Action(WorkingDirectory, Consumer, DepFS);
+    return !Tool.run(&Action);
+  });
 }

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=370425&r1=370424&r2=370425&view=diff
==============================================================================
--- cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp (original)
+++ cfe/trunk/tools/clang-scan-deps/ClangScanDeps.cpp Thu Aug 29 18:25:57 2019
@@ -51,11 +51,67 @@ public:
                          SharedStream &OS, SharedStream &Errs)
       : Worker(Service), Compilations(Compilations), OS(OS), Errs(Errs) {}
 
+  /// Print out the dependency information into a string using the dependency
+  /// file format that is specified in the options (-MD is the default) and
+  /// return it.
+  ///
+  /// \returns A \c StringError with the diagnostic output if clang errors
+  /// occurred, dependency file contents otherwise.
+  llvm::Expected<std::string> getDependencyFile(const std::string &Input,
+                                                StringRef CWD) {
+    /// Prints out all of the gathered dependencies into a string.
+    class DependencyPrinterConsumer : public DependencyConsumer {
+    public:
+      void handleFileDependency(const DependencyOutputOptions &Opts,
+                                StringRef File) override {
+        if (!this->Opts)
+          this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
+        Dependencies.push_back(File);
+      }
+
+      void printDependencies(std::string &S) {
+        if (!Opts)
+          return;
+
+        class DependencyPrinter : public DependencyFileGenerator {
+        public:
+          DependencyPrinter(DependencyOutputOptions &Opts,
+                            ArrayRef<std::string> Dependencies)
+              : DependencyFileGenerator(Opts) {
+            for (const auto &Dep : Dependencies)
+              addDependency(Dep);
+          }
+
+          void printDependencies(std::string &S) {
+            llvm::raw_string_ostream OS(S);
+            outputDependencyFile(OS);
+          }
+        };
+
+        DependencyPrinter Generator(*Opts, Dependencies);
+        Generator.printDependencies(S);
+      }
+
+    private:
+      std::unique_ptr<DependencyOutputOptions> Opts;
+      std::vector<std::string> Dependencies;
+    };
+
+    DependencyPrinterConsumer Consumer;
+    auto Result =
+        Worker.computeDependencies(Input, CWD, Compilations, Consumer);
+    if (Result)
+      return std::move(Result);
+    std::string Output;
+    Consumer.printDependencies(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 = Worker.getDependencyFile(Input, CWD, Compilations);
+    auto MaybeFile = getDependencyFile(Input, CWD);
     if (!MaybeFile) {
       llvm::handleAllErrors(
           MaybeFile.takeError(), [this, &Input](llvm::StringError &Err) {




More information about the cfe-commits mailing list