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<"<file>">;
def MG : Flag<["-"], "MG">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Add missing headers to depfile">;
+def MJ : JoinedOrSeparate<["-"], "MJ">, Group<M_Group>,
+ HelpText<"Write a compilation database entry per input">;
def MP : Flag<["-"], "MP">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Create phony target for each dependency (other than main file)">;
def MQ : JoinedOrSeparate<["-"], "MQ">, Group<M_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 &Stream, 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 &D, StringRef Filename, StringRef Target, const InputInfo &Output,
+ const InputInfo &Input, const ArgList &Args) {
+ 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 &A: Args) {
+ auto &O = 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 &it: ASL) {
+ File << ", ";
+ QuoteJSONString(File, it);
+ }
+ }
+ File << ", ";
+ Buf = "--target=";
+ Buf += Target;
+ QuoteJSONString(File, Buf);
+ File << "]},\n";
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, 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
// vice-versa.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits