ChuanqiXu updated this revision to Diff 486195.
ChuanqiXu added a comment.
Address comments from @jansvoboda11: use the style of `clang-scan-deps
-format=p1689 -- <clang_flags> -std=c++20 <input> -o <output>` instead of
`clang-scan-deps -format=p1689 --p1689-targeted-file-name=<input>
--p1689-targeted-output=<output> -- <clang_flags> -std=c++20`.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D137534/new/
https://reviews.llvm.org/D137534
Files:
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
@@ -167,9 +167,14 @@
llvm::cl::opt<std::string>
CompilationDB("compilation-database",
- llvm::cl::desc("Compilation database"), llvm::cl::Required,
+ llvm::cl::desc("Compilation database"), llvm::cl::Optional,
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 "
+ "the dependencies are to be computed."));
+
llvm::cl::opt<std::string> ModuleName(
"module-name", llvm::cl::Optional,
llvm::cl::desc("the module of which the dependencies are to be computed"),
@@ -522,19 +527,98 @@
return std::string(Path);
}
-int main(int argc, const char **argv) {
+// getCompilationDataBase - If -compilation-database is set, load the
+// compilation database from the specified file. Otherwise if the we're
+// generating P1689 format, trying to generate the compilation database
+// form specified command line after the positional parameter "--".
+static std::unique_ptr<tooling::CompilationDatabase>
+getCompilationDataBase(int argc, const char **argv, std::string &ErrorMessage) {
llvm::InitLLVM X(argc, argv);
llvm::cl::HideUnrelatedOptions(DependencyScannerCategory);
if (!llvm::cl::ParseCommandLineOptions(argc, argv))
- return 1;
+ return nullptr;
+
+ if (!CompilationDB.empty())
+ return tooling::JSONCompilationDatabase::loadFromFile(
+ CompilationDB, ErrorMessage,
+ tooling::JSONCommandLineSyntax::AutoDetect);
+ if (Format != ScanningOutputFormat::P1689) {
+ llvm::errs() << "the --compilation-database option: must be specified at "
+ "least once!";
+ return nullptr;
+ }
+
+ // Trying to get the input file, the output file and the command line options
+ // from the positional parameter "--".
+ const char **DoubleDash = std::find(argv, argv + argc, StringRef("--"));
+ if (DoubleDash == argv + argc) {
+ llvm::errs() << "The command line arguments is required after '--' in "
+ "P1689 per file mode.";
+ return nullptr;
+ }
+ std::vector<const char *> CommandLine(DoubleDash + 1, argv + argc);
+
+ std::unique_ptr<CompilerInvocation> CI = createInvocation(CommandLine);
+ if (!CI)
+ return nullptr;
+
+ FrontendOptions &FEOpts = CI->getFrontendOpts();
+ if (FEOpts.Inputs.size() != 1) {
+ llvm::errs() << "Only one input file is allowed in P1689 per file mode.";
+ return nullptr;
+ }
+
+ // FIXME: createInvocation will drop the `-o` option since it requires
+ // `-fsyntax-only`. So here we try to parse the output file manually.
+ auto CommandLineIter =
+ std::find(CommandLine.rbegin(), CommandLine.rend(), StringRef("-o"));
+ if (CommandLineIter == CommandLine.rend() ||
+ --CommandLineIter == CommandLine.rend()) {
+ llvm::errs() << "The output file is required in P1689 per file mode.";
+ return nullptr;
+ }
+ StringRef OutputFile = *CommandLineIter;
+
+ class InplaceCompilationDatabase : public tooling::CompilationDatabase {
+ public:
+ InplaceCompilationDatabase(StringRef InputFile, StringRef OutputFile,
+ ArrayRef<const char *> CommandLine)
+ : Command(".", InputFile, {}, OutputFile) {
+ for (auto *C : CommandLine)
+ Command.CommandLine.push_back(C);
+ }
+
+ std::vector<tooling::CompileCommand>
+ getCompileCommands(StringRef FilePath) const override {
+ if (FilePath != Command.Filename)
+ return {};
+ return {Command};
+ }
+
+ std::vector<std::string> getAllFiles() const override {
+ return {Command.Filename};
+ }
+
+ std::vector<tooling::CompileCommand>
+ getAllCompileCommands() const override {
+ return {Command};
+ }
+
+ private:
+ tooling::CompileCommand Command;
+ };
+
+ return std::make_unique<InplaceCompilationDatabase>(
+ FEOpts.Inputs[0].getFile(), OutputFile, CommandLine);
+}
+
+int main(int argc, const char **argv) {
std::string ErrorMessage;
- std::unique_ptr<tooling::JSONCompilationDatabase> Compilations =
- tooling::JSONCompilationDatabase::loadFromFile(
- CompilationDB, ErrorMessage,
- tooling::JSONCommandLineSyntax::AutoDetect);
+ std::unique_ptr<tooling::CompilationDatabase> Compilations =
+ getCompilationDataBase(argc, argv, ErrorMessage);
if (!Compilations) {
- llvm::errs() << "error: " << ErrorMessage << "\n";
+ llvm::errs() << ErrorMessage << "\n";
return 1;
}
Index: clang/test/ClangScanDeps/P1689.cppm
===================================================================
--- clang/test/ClangScanDeps/P1689.cppm
+++ clang/test/ClangScanDeps/P1689.cppm
@@ -5,6 +5,23 @@
// RUN: sed "s|DIR|%/t|g" %t/P1689.json.in > %t/P1689.json
// RUN: clang-scan-deps -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t
// RUN: clang-scan-deps --mode=preprocess-dependency-directives -compilation-database %t/P1689.json -format=p1689 | FileCheck %t/Checks.cpp -DPREFIX=%/t
+//
+// Check the separated dependency format.
+// RUN: clang-scan-deps -format=p1689 \
+// RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/M.cppm -o %t/M.o \
+// RUN: | FileCheck %t/M.cppm -DPREFIX=%/t
+// RUN: clang-scan-deps -format=p1689 \
+// RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/Impl.cpp -o %t/Impl.o \
+// RUN: | FileCheck %t/Impl.cpp -DPREFIX=%/t
+// 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: | FileCheck %t/impl_part.cppm -DPREFIX=%/t
+// RUN: clang-scan-deps -format=p1689 \
+// RUN: -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t %t/interface_part.cppm -o %t/interface_part.o \
+// RUN: | FileCheck %t/interface_part.cppm -DPREFIX=%/t
+// 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
//--- P1689.json.in
[
@@ -47,6 +64,31 @@
import :impl_part;
export void Hello();
+// CHECK: {
+// CHECK-NEXT: "revision": 0,
+// CHECK-NEXT: "rules": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "primary-output": "[[PREFIX]]/M.o",
+// CHECK-NEXT: "provides": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "is-interface": true,
+// CHECK-NEXT: "logical-name": "M",
+// CHECK-NEXT: "source-path": "[[PREFIX]]/M.cppm"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "requires": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "M:interface_part"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "M:impl_part"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "version": 1
+// CHECK-NEXT: }
+
//--- Impl.cpp
module;
#include "header.mock"
@@ -55,6 +97,21 @@
std::cout << "Hello ";
}
+// CHECK: {
+// CHECK-NEXT: "revision": 0,
+// CHECK-NEXT: "rules": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "primary-output": "[[PREFIX]]/Impl.o",
+// CHECK-NEXT: "requires": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "M"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "version": 1
+// CHECK-NEXT: }
+
//--- impl_part.cppm
module;
#include "header.mock"
@@ -66,10 +123,53 @@
std::cout << W << std::endl;
}
+// CHECK: {
+// CHECK-NEXT: "revision": 0,
+// CHECK-NEXT: "rules": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "primary-output": "[[PREFIX]]/impl_part.o",
+// CHECK-NEXT: "provides": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "is-interface": false,
+// CHECK-NEXT: "logical-name": "M:impl_part",
+// CHECK-NEXT: "source-path": "[[PREFIX]]/impl_part.cppm"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "requires": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "M:interface_part"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "version": 1
+// CHECK-NEXT: }
+
+// CHECK-MAKE: [[PREFIX]]/impl_part.o.ddi:
+// CHECK-MAKE: [[PREFIX]]/impl_part.cppm
+// CHECK-MAKE: [[PREFIX]]/header.mock
+
//--- interface_part.cppm
export module M:interface_part;
export void World();
+// CHECK: {
+// CHECK-NEXT: "revision": 0,
+// CHECK-NEXT: "rules": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "primary-output": "[[PREFIX]]/interface_part.o",
+// CHECK-NEXT: "provides": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "is-interface": true,
+// CHECK-NEXT: "logical-name": "M:interface_part",
+// CHECK-NEXT: "source-path": "[[PREFIX]]/interface_part.cppm"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "version": 1
+// CHECK-NEXT: }
+
//--- User.cpp
import M;
import third_party_module;
@@ -79,6 +179,24 @@
return 0;
}
+// CHECK: {
+// CHECK-NEXT: "revision": 0,
+// CHECK-NEXT: "rules": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "primary-output": "[[PREFIX]]/User.o",
+// CHECK-NEXT: "requires": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "M"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "logical-name": "third_party_module"
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "version": 1
+// CHECK-NEXT: }
+
//--- Checks.cpp
// CHECK: {
// CHECK-NEXT: "revision": 0,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits