ChuanqiXu created this revision.
ChuanqiXu added reviewers: ben.boeckel, Bigcheese, jansvoboda11.
Herald added a project: All.
ChuanqiXu requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Required in https://reviews.llvm.org/D137534.
The build systems needs the information to know that "header X changed,
scanning may have changed, so please rerun scanning". Although it is possible
to get the information by running clang-scan-deps for the second time with make
format, it is not user friendly clearly.
Repository:
rG LLVM Github Monorepo
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
@@ -187,6 +187,13 @@
"dependencies are to be computed."),
llvm::cl::cat(DependencyScannerCategory));
+llvm::cl::opt<std::string> P1689MakeformatOutputpath(
+ "p1689-makeformat-output", llvm::cl::Optional,
+ llvm::cl::desc("Only supported for P1689. Print the make-style dependency "
+ "output to the specified output. This is a helper for build "
+ "systems to do duplicate scanning."),
+ llvm::cl::cat(DependencyScannerCategory));
+
llvm::cl::opt<std::string> P1689TargettedCommand(
llvm::cl::Positional, llvm::cl::ZeroOrMore,
llvm::cl::desc("The command line flags for the target of which "
@@ -584,6 +591,19 @@
return std::move(FixedCompilationDatabase);
}
+static raw_ostream &getDependencyOS() {
+ if (!P1689MakeformatOutputpath.empty()) {
+ std::error_code EC;
+ static llvm::raw_fd_ostream OS(P1689MakeformatOutputpath, EC);
+ if (EC)
+ llvm::errs() << "Failed to open P1689 make format output file \""
+ << P1689MakeformatOutputpath << "\" for " << EC.message()
+ << "\n";
+ return OS;
+ }
+ return llvm::outs();
+}
+
int main(int argc, const char **argv) {
std::string ErrorMessage;
std::unique_ptr<tooling::CompilationDatabase> Compilations =
@@ -662,7 +682,7 @@
SharedStream Errs(llvm::errs());
// Print out the dependency results to STDOUT by default.
- SharedStream DependencyOS(llvm::outs());
+ SharedStream DependencyOS(getDependencyOS());
DependencyScanningService Service(ScanMode, Format, OptimizeArgs,
EagerLoadModules);
@@ -722,10 +742,20 @@
Errs))
HadErrors = true;
} else if (Format == ScanningOutputFormat::P1689) {
+ llvm::Optional<std::string> MakeformatOutput;
+ if (!P1689MakeformatOutputpath.empty())
+ MakeformatOutput.emplace();
+
auto MaybeRule = WorkerTools[I]->getP1689ModuleDependencyFile(
- *Input, CWD, MaybeModuleName);
- if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs))
- HadErrors = true;
+ *Input, CWD, MakeformatOutput, MaybeModuleName);
+ HadErrors =
+ handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs);
+
+ if (MakeformatOutput && !MakeformatOutput->empty() && !HadErrors) {
+ llvm::Expected<std::string> MaybeOutput(*MakeformatOutput);
+ HadErrors = handleMakeDependencyToolResult(Filename, MaybeOutput,
+ DependencyOS, 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,14 @@
// RUN: clang-scan-deps -format=p1689 --p1689-targeted-file-name=%t/User.cpp --p1689-targeted-output=%t/User.o \
// RUN: -- -std=c++20 -c \
// RUN: | FileCheck %t/User.cpp -DPREFIX=%/t
+//
+// Check we can generate the make-style dependencies as expected.
+// RUN: clang-scan-deps --compilation-database %t/P1689.json -format=p1689 --p1689-makeformat-output=%t/P1689.dep
+// RUN: cat %t/P1689.dep | FileCheck %t/Checks.cpp -DPREFIX=%/t --check-prefix=CHECK-MAKE
+//
+// RUN: clang-scan-deps -format=p1689 --p1689-targeted-file-name=%t/impl_part.cppm --p1689-targeted-output=%t/impl_part.o \
+// RUN: --p1689-makeformat-output=%t/impl_part.dep -- -std=c++20 -c
+// RUN: cat %t/impl_part.dep | FileCheck %t/impl_part.cppm -DPREFIX=%/t --check-prefix=CHECK-MAKE
//--- P1689.json.in
[
@@ -57,7 +65,6 @@
}
]
-
//--- M.cppm
export module M;
export import :interface_part;
@@ -145,6 +152,10 @@
// CHECK-NEXT: "version": 1
// CHECK-NEXT: }
+// CHECK-MAKE: [[PREFIX]]/impl_part.o:
+// CHECK-MAKE: [[PREFIX]]/impl_part.cppm
+// CHECK-MAKE: [[PREFIX]]/header.mock
+
//--- interface_part.cppm
export module M:interface_part;
export void World();
@@ -268,4 +279,17 @@
// CHECK-NEXT: "version": 1
// CHECK-NEXT: }
+// CHECK-MAKE-DAG: [[PREFIX]]/User.o:
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/User.cpp
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/Impl.o:
+// CHECK-MAKE-DAG: [[PREFIX]]/Impl.cpp
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/header.mock
+// CHECK-MAKE-DAG: [[PREFIX]]/M.o:
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/M.cppm
+// CHECK-MAKE-DAG: [[PREFIX]]/interface_part.o:
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/interface_part.cppm
+// CHECK-MAKE-DAG: [[PREFIX]]/impl_part.o:
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/impl_part.cppm
+// CHECK-MAKE-DAG-NEXT: [[PREFIX]]/header.mock
+
//--- header.mock
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,
+ llvm::Optional<std::string> &MakeformatOutput,
llvm::Optional<StringRef> ModuleName) {
- class P1689ModuleDependencyPrinterConsumer : public DependencyConsumer {
+ class P1689ModuleDependencyPrinterConsumer
+ : public MakeDependencyPrinterConsumer {
public:
P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
const CompileCommand &Command)
@@ -122,14 +126,13 @@
}
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");
+ handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
+ MakeDependencyPrinterConsumer::handleDependencyOutputOpts(Opts);
+ /// NOTE: Currently, the compiler will generate module unit (.cppm) files
+ /// into module file (.pcm) first. Then it compiles the module file (.pcm)
+ /// into object files. It results that the Targets[0] here will be .pcm
+ /// file instead of the expected output file.
+ this->Opts->Targets[0] = Rule.PrimaryOutput;
}
void handleProvidedAndRequiredStdCXXModules(
@@ -152,6 +155,8 @@
ModuleName);
if (Result)
return std::move(Result);
+ if (MakeformatOutput)
+ 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,9 +92,17 @@
getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD,
llvm::Optional<StringRef> ModuleName = None);
+ /// Collect the module dependency in P1689 format for C++20 named modules.
+ ///
+ /// \param MakeformatOutput The output parameter for dependency information
+ /// in make format if \p MakeformatOutput isn't none.
+ ///
+ /// \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<std::string> &MakeformatOutput,
llvm::Optional<StringRef> ModuleName = None);
/// Collect the full module dependency graph for the input, ignoring any
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits