ChuanqiXu updated this revision to Diff 486196.
ChuanqiXu added a comment.

Update since https://reviews.llvm.org/D137534 changes.


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

https://reviews.llvm.org/D139168

Files:
  clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
  clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
  clang/test/ClangScanDeps/P1689.cppm
  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
@@ -751,10 +751,33 @@
                                              Errs))
             HadErrors = true;
         } else if (Format == ScanningOutputFormat::P1689) {
+          // It is useful to generate the make-format dependency output during
+          // the scanning for P1689. Otherwise the users need to scan again for
+          // it. We will generate the make-format dependency output if we find
+          // `-MF` in the command lines.
+          std::string MakeformatOutputPath;
+          std::string MakeformatOutput;
+
           auto MaybeRule = WorkerTools[I]->getP1689ModuleDependencyFile(
-              *Input, CWD, MaybeModuleName);
-          if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs))
-            HadErrors = true;
+              *Input, CWD, MakeformatOutput, MakeformatOutputPath,
+              MaybeModuleName);
+          HadErrors =
+              handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs);
+
+          if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() &&
+              !HadErrors) {
+            std::error_code EC;
+            llvm::raw_fd_ostream OS(MakeformatOutputPath, EC);
+            if (EC)
+              llvm::errs() << "Failed to open P1689 make format output file \""
+                           << MakeformatOutputPath << "\" for " << EC.message()
+                           << "\n";
+            SharedStream MakeformatOS(OS);
+
+            llvm::Expected<std::string> MaybeOutput(MakeformatOutput);
+            HadErrors = handleMakeDependencyToolResult(Filename, MaybeOutput,
+                                                       MakeformatOS, Errs);
+          }
         } else if (DeprecatedDriverCommand) {
           auto MaybeFullDeps =
               WorkerTools[I]->getFullDependenciesLegacyDriverCommand(
Index: clang/test/ClangScanDeps/P1689.cppm
===================================================================
--- clang/test/ClangScanDeps/P1689.cppm
+++ clang/test/ClangScanDeps/P1689.cppm
@@ -22,6 +22,12 @@
 // RUN: clang-scan-deps -format=p1689 \
 // RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/User.cpp -o %t/User.o \
 // RUN:   | FileCheck %t/User.cpp -DPREFIX=%/t
+//
+// Check we can generate the make-style dependencies as expected.
+// RUN: clang-scan-deps -format=p1689 \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/impl_part.cppm -o %t/impl_part.o \
+// RUN:      -MT %t/impl_part.o.ddi -MD -MF %t/impl_part.dep
+// RUN:   cat %t/impl_part.dep | FileCheck %t/impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE
 
 //--- P1689.json.in
 [
@@ -57,7 +63,6 @@
 }
 ]
 
-
 //--- M.cppm
 export module M;
 export import :interface_part;
Index: clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
===================================================================
--- clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
+++ clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
@@ -39,67 +39,69 @@
     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
     : Worker(Service, std::move(FS)) {}
 
-llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
-    const std::vector<std::string> &CommandLine, StringRef CWD,
-    llvm::Optional<StringRef> ModuleName) {
-  /// Prints out all of the gathered dependencies into a string.
-  class MakeDependencyPrinterConsumer : public DependencyConsumer {
-  public:
-    void handleBuildCommand(Command) override {}
+namespace {
+/// Prints out all of the gathered dependencies into a string.
+class MakeDependencyPrinterConsumer : public DependencyConsumer {
+public:
+  void handleBuildCommand(Command) override {}
+
+  void
+  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
+    this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
+  }
 
-    void
-    handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
-      this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
-    }
+  void handleFileDependency(StringRef File) override {
+    Dependencies.push_back(std::string(File));
+  }
 
-    void handleFileDependency(StringRef File) override {
-      Dependencies.push_back(std::string(File));
-    }
+  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
+    // Same as `handleModuleDependency`.
+  }
 
-    void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
-      // Same as `handleModuleDependency`.
-    }
+  void handleModuleDependency(ModuleDeps MD) override {
+    // These are ignored for the make format as it can't support the full
+    // set of deps, and handleFileDependency handles enough for implicitly
+    // built modules to work.
+  }
 
-    void handleModuleDependency(ModuleDeps MD) override {
-      // These are ignored for the make format as it can't support the full
-      // set of deps, and handleFileDependency handles enough for implicitly
-      // built modules to work.
-    }
+  void handleContextHash(std::string Hash) override {}
 
-    void handleContextHash(std::string Hash) override {}
+  std::string lookupModuleOutput(const ModuleID &ID,
+                                 ModuleOutputKind Kind) override {
+    llvm::report_fatal_error("unexpected call to lookupModuleOutput");
+  }
 
-    std::string lookupModuleOutput(const ModuleID &ID,
-                                   ModuleOutputKind Kind) override {
-      llvm::report_fatal_error("unexpected call to lookupModuleOutput");
-    }
+  void printDependencies(std::string &S) {
+    assert(Opts && "Handled dependency output options.");
 
-    void printDependencies(std::string &S) {
-      assert(Opts && "Handled dependency output options.");
-
-      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);
-    }
+    class DependencyPrinter : public DependencyFileGenerator {
+    public:
+      DependencyPrinter(DependencyOutputOptions &Opts,
+                        ArrayRef<std::string> Dependencies)
+          : DependencyFileGenerator(Opts) {
+        for (const auto &Dep : Dependencies)
+          addDependency(Dep);
+      }
 
-  private:
-    std::unique_ptr<DependencyOutputOptions> Opts;
-    std::vector<std::string> Dependencies;
-  };
+      void printDependencies(std::string &S) {
+        llvm::raw_string_ostream OS(S);
+        outputDependencyFile(OS);
+      }
+    };
 
+    DependencyPrinter Generator(*Opts, Dependencies);
+    Generator.printDependencies(S);
+  }
+
+protected:
+  std::unique_ptr<DependencyOutputOptions> Opts;
+  std::vector<std::string> Dependencies;
+};
+} // anonymous namespace
+
+llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
+    const std::vector<std::string> &CommandLine, StringRef CWD,
+    llvm::Optional<StringRef> ModuleName) {
   MakeDependencyPrinterConsumer Consumer;
   auto Result =
       Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
@@ -112,8 +114,10 @@
 
 llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
     const clang::tooling::CompileCommand &Command, StringRef CWD,
+    std::string &MakeformatOutput, std::string &MakeformatOutputPath,
     llvm::Optional<StringRef> ModuleName) {
-  class P1689ModuleDependencyPrinterConsumer : public DependencyConsumer {
+  class P1689ModuleDependencyPrinterConsumer
+      : public MakeDependencyPrinterConsumer {
   public:
     P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
                                          const CompileCommand &Command)
@@ -121,17 +125,6 @@
       Rule.PrimaryOutput = Command.Output;
     }
 
-    void
-    handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {}
-    void handleFileDependency(StringRef File) override {}
-    void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}
-    void handleModuleDependency(ModuleDeps MD) override {}
-    void handleContextHash(std::string Hash) override {}
-    std::string lookupModuleOutput(const ModuleID &ID,
-                                   ModuleOutputKind Kind) override {
-      llvm::report_fatal_error("unexpected call to lookupModuleOutput");
-    }
-
     void handleProvidedAndRequiredStdCXXModules(
         llvm::Optional<ModuleID> Provided,
         std::vector<ModuleID> Requires) override {
@@ -141,6 +134,12 @@
       Rule.Requires = Requires;
     }
 
+    StringRef getMakeFormatDependencyOutputPath() {
+      if (Opts->OutputFormat != DependencyOutputFormat::Make)
+        return {};
+      return Opts->OutputFile;
+    }
+
   private:
     StringRef Filename;
     clang::tooling::dependencies::P1689Rule &Rule;
@@ -152,6 +151,10 @@
                                            ModuleName);
   if (Result)
     return std::move(Result);
+
+  MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
+  if (!MakeformatOutputPath.empty())
+    Consumer.printDependencies(MakeformatOutput);
   return Rule;
 }
 
Index: clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
===================================================================
--- clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -92,10 +92,22 @@
   getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD,
                     llvm::Optional<StringRef> ModuleName = std::nullopt);
 
+  /// Collect the module dependency in P1689 format for C++20 named modules.
+  ///
+  /// \param MakeformatOutput The output parameter for dependency information
+  /// in make format if the command line requires to generate make-format
+  /// dependency information by `-MD -MF <dep_file>`.
+  ///
+  /// \param MakeformatOutputPath The output parameter for the path to
+  /// \param MakeformatOutput.
+  ///
+  /// \returns A \c StringError with the diagnostic output if clang errors
+  /// occurred, P1689 dependency format rules otherwise.
   llvm::Expected<clang::tooling::dependencies::P1689Rule>
-  getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command,
-                               StringRef CWD,
-                               llvm::Optional<StringRef> ModuleName = std::nullopt);
+  getP1689ModuleDependencyFile(
+      const clang::tooling::CompileCommand &Command, StringRef CWD,
+      std::string &MakeformatOutput, std::string &MakeformatOutputPath,
+      llvm::Optional<StringRef> ModuleName = std::nullopt);
 
   /// Collect the full module dependency graph for the input, ignoring any
   /// modules which have already been seen. If \p ModuleName isn't empty, this
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to