diff options
author | Joerg Sonnenberger <joerg@bec.de> | 2016-12-06 16:33:22 +0000 |
---|---|---|
committer | Joerg Sonnenberger <joerg@bec.de> | 2016-12-06 16:33:22 +0000 |
commit | cbc872549cf8be53e2558a13de643e3bb79673f6 (patch) | |
tree | 6fa6b673d9d2ac88e6e192e1cff8fd4fc701b848 /clang/lib/Driver/Tools.cpp | |
parent | 0caaadfc2d8ebc5fdb035533c962fe316e8c9905 (diff) | |
download | llvm-cbc872549cf8be53e2558a13de643e3bb79673f6.zip llvm-cbc872549cf8be53e2558a13de643e3bb79673f6.tar.gz llvm-cbc872549cf8be53e2558a13de643e3bb79673f6.tar.bz2 |
Allow clang to write compilation database records.
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
or some additional filtering to remove the trailing comma for strict
JSON compliance.
Differential Revision: https://reviews.llvm.org/D27140
llvm-svn: 288821
Diffstat (limited to 'clang/lib/Driver/Tools.cpp')
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 4ca2663..ac7309c 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/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 <unistd.h> // For getuid(). @@ -4030,6 +4030,60 @@ static void AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back("-KPIC"); } +void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename, + StringRef Target, const InputInfo &Output, + const InputInfo &Input, const ArgList &Args) 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 &D = getToolChain().getDriver(); + + if (!CompilationDatabase) { + std::error_code EC; + auto File = llvm::make_unique<llvm::raw_fd_ostream>(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 &CDB = *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 &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 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 &it: ASL) + CDB << ", \"" << escape(it) << "\""; + } + Buf = "--target="; + Buf += Target; + CDB << ", \"" << escape(Buf) << "\"]},\n"; +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { @@ -4074,6 +4128,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-triple"); CmdArgs.push_back(Args.MakeArgString(TripleStr)); + if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) { + DumpCompilationDatabase(C, 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. |