[PATCH] D27140: Allow clang to write compilation database records
This revision was automatically updated to reflect the committed changes. Closed by commit rL288821: Allow clang to write compilation database records. (authored by joerg). Changed prior to commit: https://reviews.llvm.org/D27140?vs=79997=80429#toc Repository: rL LLVM https://reviews.llvm.org/D27140 Files: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td cfe/trunk/include/clang/Driver/Options.td cfe/trunk/lib/Driver/Tools.cpp cfe/trunk/lib/Driver/Tools.h cfe/trunk/test/Driver/compilation_database.c Index: cfe/trunk/include/clang/Driver/Options.td === --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -266,6 +266,8 @@ MetaVarName<"">; def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to depfile">; +def MJ : JoinedOrSeparate<["-"], "MJ">, Group, +HelpText<"Write a compilation database entry per input">; def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>, HelpText<"Create phony target for each dependency (other than main file)">; def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>, Index: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td === --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td @@ -87,6 +87,8 @@ "the clang compiler does not support '%0' for C++ on Darwin/i386">; def err_drv_command_failed : Error< "%0 command failed with exit code %1 (use -v to see invocation)">; +def err_drv_compilationdatabase : Error< + "compilation database '%0' could not be opened: %1">; def err_drv_command_signalled : Error< "%0 command failed due to signal (use -v to see invocation)">; def err_drv_force_crash : Error< Index: cfe/trunk/test/Driver/compilation_database.c === --- cfe/trunk/test/Driver/compilation_database.c +++ cfe/trunk/test/Driver/compilation_database.c @@ -0,0 +1,10 @@ +// RUN: %clang -MD -MP -c -x c %s -xc++ %s -Wall -MJ - 2>&1 | FileCheck %s +// RUN: not %clang -c -x c %s -MJ %s/non-existant 2>&1 | FileCheck --check-prefix=ERROR %s + +// CHECK: { "directory": "[[CWD:[^"]+]]", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc", "[[SRC]]", "-c", "-Wall", "--target={{[^"]+}}"]}, +// CHECK: { "directory": "[[CWD:[^"]+]]", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc++", "[[SRC]]", "-c", "-Wall", "--target={{[^"]+}}"]}, +// ERROR: error: compilation database '{{.*}}/non-existant' could not be opened: + +int main(void) { + return 0; +} Index: cfe/trunk/lib/Driver/Tools.h === --- cfe/trunk/lib/Driver/Tools.h +++ cfe/trunk/lib/Driver/Tools.h @@ -17,6 +17,7 @@ #include "clang/Driver/Util.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/Option.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -101,6 +102,12 @@ mutable std::unique_ptr CLFallback; + mutable std::unique_ptr CompilationDatabase = nullptr; + void DumpCompilationDatabase(Compilation , StringRef Filename, + StringRef Target, + const InputInfo , const InputInfo , + const llvm::opt::ArgList ) const; + public: // CAUTION! The first constructor argument ("clang") is not arbitrary, // as it is for other tools. Some operations on a Tool actually test Index: cfe/trunk/lib/Driver/Tools.cpp === --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -40,9 +40,9 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -4030,6 +4030,60 @@ CmdArgs.push_back("-KPIC"); } +void Clang::DumpCompilationDatabase(Compilation , StringRef Filename, +StringRef Target, const InputInfo , +const InputInfo , const ArgList ) const { + // If this is a dry run, do not create the compilation database file. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) +return; + + using llvm::yaml::escape; + const Driver = getToolChain().getDriver(); + + if (!CompilationDatabase) { +std::error_code EC; +auto File = llvm::make_unique(Filename, EC, llvm::sys::fs::F_Text); +if (EC) { + D.Diag(clang::diag::err_drv_compilationdatabase) <<
[PATCH] D27140: Allow clang to write compilation database records
klimek accepted this revision. klimek added a comment. This revision is now accepted and ready to land. LG. We can always add more intricate ways later on. Repository: rL LLVM https://reviews.llvm.org/D27140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27140: Allow clang to write compilation database records
arichardson added a comment. It would also be good to append --sysroot=DEFAULT_SYSROOT if DEFAULT_SYSROOT is not empty and there is no explicit --sysroot flag. That way the compilation database can also be consumed by a libclang based too that does not have the same DEFAULT_SYSROOT set. Repository: rL LLVM https://reviews.llvm.org/D27140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27140: Allow clang to write compilation database records
joerg added a comment. Ping Repository: rL LLVM https://reviews.llvm.org/D27140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27140: Allow clang to write compilation database records
joerg updated the summary for this revision. joerg set the repository for this revision to rL LLVM. joerg updated this revision to Diff 79997. joerg added a comment. Add test case. Repository: rL LLVM https://reviews.llvm.org/D27140 Files: include/clang/Basic/DiagnosticDriverKinds.td include/clang/Driver/Options.td lib/Driver/Tools.cpp lib/Driver/Tools.h test/Driver/compilation_database.c Index: test/Driver/compilation_database.c === --- test/Driver/compilation_database.c +++ test/Driver/compilation_database.c @@ -0,0 +1,10 @@ +// RUN: %clang -MD -MP -c -x c %s -xc++ %s -Wall -MJ - 2>&1 | FileCheck %s +// RUN: not %clang -c -x c %s -MJ %s/non-existant 2>&1 | FileCheck --check-prefix=ERROR %s + +// CHECK: { "directory": "[[CWD:[^"]+]]", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc", "[[SRC]]", "-c", "-Wall", "--target={{[^"]+}}"]}, +// CHECK: { "directory": "[[CWD:[^"]+]]", "file": "[[SRC:[^"]+[/|\\]compilation_database.c]]", "output": "compilation_database.o", "arguments": ["{{[^"]*}}clang{{[^"]*}}", "-xc++", "[[SRC]]", "-c", "-Wall", "--target={{[^"]+}}"]}, +// ERROR: error: compilation database '{{.*}}/non-existant' could not be opened: + +int main(void) { + return 0; +} Index: lib/Driver/Tools.h === --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -17,6 +17,7 @@ #include "clang/Driver/Util.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/Option.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -101,6 +102,12 @@ mutable std::unique_ptr CLFallback; + mutable std::unique_ptr CompilationDatabase = nullptr; + void DumpCompilationDatabase(Compilation , StringRef Filename, + StringRef Target, + const InputInfo , const InputInfo , + const llvm::opt::ArgList ) const; + public: // CAUTION! The first constructor argument ("clang") is not arbitrary, // as it is for other tools. Some operations on a Tool actually test Index: lib/Driver/Tools.cpp === --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -40,9 +40,9 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -4005,6 +4005,60 @@ CmdArgs.push_back("-KPIC"); } +void Clang::DumpCompilationDatabase(Compilation , StringRef Filename, +StringRef Target, const InputInfo , +const InputInfo , const ArgList ) const { + // If this is a dry run, do not create the compilation database file. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) +return; + + using llvm::yaml::escape; + const Driver = getToolChain().getDriver(); + + if (!CompilationDatabase) { +std::error_code EC; +auto File = llvm::make_unique(Filename, EC, llvm::sys::fs::F_Text); +if (EC) { + D.Diag(clang::diag::err_drv_compilationdatabase) << Filename + << EC.message(); + return; +} +CompilationDatabase = std::move(File); + } + auto = *CompilationDatabase; + SmallString<128> Buf; + if (llvm::sys::fs::current_path(Buf)) +Buf = "."; + CDB << "{ \"directory\": \"" << escape(Buf) << "\""; + CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\""; + CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\""; + CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\""; + Buf = "-x"; + Buf += types::getTypeName(Input.getType()); + CDB << ", \"" << escape(Buf) << "\""; + CDB << ", \"" << escape(Input.getFilename()) << "\""; + for (auto : Args) { +auto = A->getOption(); +// Skip language selection, which is positional. +if (O.getID() == options::OPT_x) + continue; +// Skip writing dependency output and the compilation database itself. +if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) + continue; +// Skip inputs. +if (O.getKind() == Option::InputClass) + continue; +// All other arguments are quoted and appended. +ArgStringList ASL; +A->render(Args, ASL); +for (auto : ASL) + CDB << ", \"" << escape(it) << "\""; + } + Buf = "--target="; + Buf += Target; + CDB << ", \"" << escape(Buf) << "\"]},\n"; +} + void Clang::ConstructJob(Compilation , const JobAction , const InputInfo , const InputInfoList , const ArgList , const char *LinkingOutput)
[PATCH] D27140: Allow clang to write compilation database records
klimek added reviewers: bkramer, akyrtzi. klimek added a comment. Adding some folks. One question is whether we can use the additional output stuff doug added at some point for this. https://reviews.llvm.org/D27140 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27140: Allow clang to write compilation database records
joerg updated this revision to Diff 79482. joerg added a comment. Move implementation into the Clang class, keep track of the raw_fd_stream. This avoids reopening it on multiple inputs and removes the need for append mode. Short circuit the function when -### is present. Add proper diagnostics on open failure. Still not completely happy with the place and the associated need for the mutable member. https://reviews.llvm.org/D27140 Files: docs/JSONCompilationDatabase.rst include/clang/Basic/DiagnosticDriverKinds.td include/clang/Driver/Options.td lib/Driver/Tools.cpp lib/Driver/Tools.h Index: lib/Driver/Tools.h === --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -17,6 +17,7 @@ #include "clang/Driver/Util.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/Option.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -101,6 +102,11 @@ mutable std::unique_ptr CLFallback; + mutable std::unique_ptr CompilationDatabase = nullptr; + void DumpCompilationDatabase(StringRef Filename, StringRef Target, + const InputInfo , const InputInfo , + const llvm::opt::ArgList ) const; + public: // CAUTION! The first constructor argument ("clang") is not arbitrary, // as it is for other tools. Some operations on a Tool actually test Index: lib/Driver/Tools.cpp === --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -40,9 +40,9 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -4002,6 +4002,60 @@ CmdArgs.push_back("-KPIC"); } +void Clang::DumpCompilationDatabase(StringRef Filename, StringRef Target, const InputInfo , +const InputInfo , const ArgList ) const { + + // If this is a dry run, do not create the compilation database file. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) +return; + + using llvm::yaml::escape; + const Driver = getToolChain().getDriver(); + + if (!CompilationDatabase) { +std::error_code EC; +auto File = llvm::make_unique(Filename, EC, llvm::sys::fs::F_Text); +if (EC) { + D.Diag(clang::diag::err_drv_compilationdatabase) << Filename + << EC.message(); + return; +} +CompilationDatabase = std::move(File); + } + auto = *CompilationDatabase; + SmallString<128> Buf; + if (llvm::sys::fs::current_path(Buf)) +Buf = "."; + CDB << "{ \"directory\": \"" << escape(Buf) << "\""; + CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\""; + CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\""; + CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\""; + Buf = "-x"; + Buf += types::getTypeName(Input.getType()); + CDB << ", \"" << escape(Buf) << "\""; + CDB << ", \"" << escape(Input.getFilename()) << "\""; + for (auto : Args) { +auto = A->getOption(); +// Skip language selection, which is positional. +if (O.getID() == options::OPT_x) + continue; +// Skip writing dependency output and the compilation database itself. +if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) + continue; +// Skip inputs. +if (O.getKind() == Option::InputClass) + continue; +// All other arguments are quoted and appended. +ArgStringList ASL; +A->render(Args, ASL); +for (auto : ASL) + CDB << ", \"" << escape(it) << "\""; + } + Buf = "--target="; + Buf += Target; + CDB << ", \"" << escape(Buf) << "\"]},\n"; +} + void Clang::ConstructJob(Compilation , const JobAction , const InputInfo , const InputInfoList , const ArgList , const char *LinkingOutput) const { @@ -4046,6 +4100,11 @@ CmdArgs.push_back("-triple"); CmdArgs.push_back(Args.MakeArgString(TripleStr)); + if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) { +DumpCompilationDatabase(MJ->getValue(), TripleStr, Output, Input, Args); +Args.ClaimAllArgs(options::OPT_MJ); + } + if (IsCuda) { // We have to pass the triple of the host if compiling for a CUDA device and // vice-versa. Index: include/clang/Driver/Options.td === --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -266,6 +266,8 @@ MetaVarName<"">; def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to depfile">; +def MJ : JoinedOrSeparate<["-"], "MJ">, Group, +HelpText<"Write a compilation database entry per
[PATCH] D27140: Allow clang to write compilation database records
joerg removed rL LLVM as the repository for this revision. joerg updated this revision to Diff 79423. joerg added a comment. Use llvm::yaml::escape. https://reviews.llvm.org/D27140 Files: include/clang/Driver/Options.td lib/Driver/Tools.cpp Index: include/clang/Driver/Options.td === --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -266,6 +266,8 @@ MetaVarName<"">; def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to depfile">; +def MJ : JoinedOrSeparate<["-"], "MJ">, Group, +HelpText<"Write a compilation database entry per input">; def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>, HelpText<"Create phony target for each dependency (other than main file)">; def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>, Index: lib/Driver/Tools.cpp === --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -43,6 +43,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/YAMLParser.h" #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -4002,6 +4003,64 @@ CmdArgs.push_back("-KPIC"); } +static void QuoteJSONString(llvm::raw_fd_ostream , StringRef Str) { + Stream << "\""; + Stream << llvm::yaml::escape(Str); + Stream << "\""; +} + +static void DumpCompilationDatabase(const Driver , StringRef Filename, StringRef Target, const InputInfo , +const InputInfo , const ArgList ) { + std::error_code EC; + llvm::raw_fd_ostream File(Filename, EC, llvm::sys::fs::F_Text | llvm::sys::fs::F_Append); + if (EC) { +//errs() << "Failed to open " << Filename << ": " << EC.message() << "\n" ; +return; + } + SmallString<128> Buf; + if (llvm::sys::fs::current_path(Buf)) +Buf = "."; + File << "{ \"directory\": "; + QuoteJSONString(File, Buf); + File << ", \"file\": "; + QuoteJSONString(File, Input.getFilename()); + File << ", \"output\": "; + QuoteJSONString(File, Output.getFilename()); + + File << ", \"arguments\": ["; + QuoteJSONString(File, D.ClangExecutable); + File << ", "; + Buf = "-x"; + Buf += types::getTypeName(Input.getType()); + QuoteJSONString(File, Buf); + File << ", "; + QuoteJSONString(File, Input.getFilename()); + for (auto : Args) { +auto = A->getOption(); +// Skip language selection, which is positional. +if (O.getID() == options::OPT_x) + continue; +// Skip writing dependency output and the compiliation database itself. +if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) + continue; +// Skip inputs. +if (O.getKind() == Option::InputClass) + continue; +// All other arguments are quoted and appended. +ArgStringList ASL; +A->render(Args, ASL); +for (auto : ASL) { + File << ", "; + QuoteJSONString(File, it); +} + } + File << ", "; + Buf = "--target="; + Buf += Target; + QuoteJSONString(File, Buf); + File << "]},\n"; +} + void Clang::ConstructJob(Compilation , const JobAction , const InputInfo , const InputInfoList , const ArgList , const char *LinkingOutput) const { @@ -4046,6 +4105,10 @@ CmdArgs.push_back("-triple"); CmdArgs.push_back(Args.MakeArgString(TripleStr)); + if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) +DumpCompilationDatabase(C.getDriver(), MJ->getValue(), TripleStr, Output, Input, Args); + Args.ClaimAllArgs(options::OPT_MJ); + if (IsCuda) { // We have to pass the triple of the host if compiling for a CUDA device and // vice-versa. ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27140: Allow clang to write compilation database records
joerg created this revision. joerg added reviewers: klimek, rsmith. joerg added a subscriber: cfe-commits. joerg set the repository for this revision to rL LLVM. joerg added a dependency: D27138: Extend CompilationDatabase by a field for the output filename. When integrating compilation database output into existing build systems, two approaches dominate so far. Ad-hoc implementation of the JSON output rules or using compiler wrappers. This patch adds a new option "-MJ foo.json" which gives a slightly cleaned up compilation record. The output is a fragment, i.e. you still need to add the array markers, but it allows multiple files to be easy merged. This way the only change in a build system is adding the option with potentially a per-target output file and merging the files with something like `(echo '['; cat *.o.json; echo ']' > compilation_database.json`. The current implementation has two issues: 1. It doesn't honor -###. This would be easily fixable though. 2. It opens the output file more than once. That's why it is currently using append mode. Fixing this requires either moving it to a different part in the processing chain or storing the stream in an appropiate place. The output record currently depends on https://reviews.llvm.org/D27138, but would be easily adjustable if necessary. I'm aware of the missing test cases, will provide them once the architectural side is clear. Repository: rL LLVM https://reviews.llvm.org/D27140 Files: include/clang/Driver/Options.td lib/Driver/Tools.cpp Index: include/clang/Driver/Options.td === --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -266,6 +266,8 @@ MetaVarName<"">; def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>, HelpText<"Add missing headers to depfile">; +def MJ : JoinedOrSeparate<["-"], "MJ">, Group, +HelpText<"Write a compilation database entry per input">; def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>, HelpText<"Create phony target for each dependency (other than main file)">; def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>, Index: lib/Driver/Tools.cpp === --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4002,6 +4002,72 @@ CmdArgs.push_back("-KPIC"); } +static void QuoteJSONString(llvm::raw_fd_ostream , StringRef Str) { + Stream << "\""; + if (Str.find_first_of("\\\"") == Str.npos) { +Stream << Str; + } else { +for (auto ch: Str) { + if (ch == '\\' || ch == '"') +Stream << '\\'; + Stream << ch; +} + } + Stream << "\""; +} + +static void DumpCompilationDatabase(const Driver , StringRef Filename, StringRef Target, const InputInfo , +const InputInfo , const ArgList ) { + std::error_code EC; + llvm::raw_fd_ostream File(Filename, EC, llvm::sys::fs::F_Text | llvm::sys::fs::F_Append); + if (EC) { +//errs() << "Failed to open " << Filename << ": " << EC.message() << "\n" ; +return; + } + SmallString<128> Buf; + if (llvm::sys::fs::current_path(Buf)) +Buf = "."; + File << "{ \"directory\": "; + QuoteJSONString(File, Buf); + File << ", \"file\": "; + QuoteJSONString(File, Input.getFilename()); + File << ", \"output\": "; + QuoteJSONString(File, Output.getFilename()); + + File << ", \"arguments\": ["; + QuoteJSONString(File, D.ClangExecutable); + File << ", "; + Buf = "-x"; + Buf += types::getTypeName(Input.getType()); + QuoteJSONString(File, Buf); + File << ", "; + QuoteJSONString(File, Input.getFilename()); + for (auto : Args) { +auto = A->getOption(); +// Skip language selection, which is positional. +if (O.getID() == options::OPT_x) + continue; +// Skip writing dependency output and the compiliation database itself. +if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group) + continue; +// Skip inputs. +if (O.getKind() == Option::InputClass) + continue; +// All other arguments are quoted and appended. +ArgStringList ASL; +A->render(Args, ASL); +for (auto : ASL) { + File << ", "; + QuoteJSONString(File, it); +} + } + File << ", "; + Buf = "--target="; + Buf += Target; + QuoteJSONString(File, Buf); + File << "]},\n"; +} + void Clang::ConstructJob(Compilation , const JobAction , const InputInfo , const InputInfoList , const ArgList , const char *LinkingOutput) const { @@ -4046,6 +4112,10 @@ CmdArgs.push_back("-triple"); CmdArgs.push_back(Args.MakeArgString(TripleStr)); + if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) +DumpCompilationDatabase(C.getDriver(), MJ->getValue(), TripleStr, Output, Input, Args); + Args.ClaimAllArgs(options::OPT_MJ); + if (IsCuda) { // We have to pass the triple of the host if compiling for a CUDA device and