Add compdb tool
authorPeter Collingbourne <peter@pcc.me.uk>
Thu, 28 Feb 2013 08:28:23 +0000 (00:28 -0800)
committerPeter Collingbourne <peter@pcc.me.uk>
Sun, 10 Mar 2013 03:22:58 +0000 (19:22 -0800)
This tool helps convert Ninja build files to a compilation database
of the form used by Clang tooling.

doc/manual.asciidoc
src/ninja.cc

index 1e5b70b..ea26b8d 100644 (file)
@@ -283,6 +283,12 @@ Files created but not referenced in the graph are not removed. This
 tool takes in account the +-v+ and the +-n+ options (note that +-n+
 implies +-v+).
 
+`compdb`:: given a list of rules, each of which is expected to be a
+C family language compiler rule whose first input is the name of the
+source file, prints on standard output a compilation database in the
+http://clang.llvm.org/docs/JSONCompilationDatabase.html[JSON format] expected
+by the Clang tooling interface.
+_Available since Ninja 1.2._
 
 
 Writing your own Ninja files
index 2b250b7..c6a3500 100644 (file)
@@ -485,6 +485,49 @@ int ToolClean(Globals* globals, int argc, char* argv[]) {
   }
 }
 
+void EncodeJSONString(const char *str) {
+  while (*str) {
+    if (*str == '"' || *str == '\\')
+      putchar('\\');
+    putchar(*str);
+    str++;
+  }
+}
+
+int ToolCompilationDatabase(Globals* globals, int argc, char* argv[]) {
+  bool first = true;
+  char cwd[PATH_MAX];
+
+  if (!getcwd(cwd, PATH_MAX)) {
+    Error("cannot determine working directory: %s", strerror(errno));
+    return 1;
+  }
+
+  putchar('[');
+  for (vector<Edge*>::iterator e = globals->state->edges_.begin();
+       e != globals->state->edges_.end(); ++e) {
+    for (int i = 0; i != argc; ++i) {
+      if ((*e)->rule_->name() == argv[i]) {
+        if (!first)
+          putchar(',');
+
+        printf("\n  {\n    \"directory\": \"");
+        EncodeJSONString(cwd);
+        printf("\",\n    \"command\": \"");
+        EncodeJSONString((*e)->EvaluateCommand().c_str());
+        printf("\",\n    \"file\": \"");
+        EncodeJSONString((*e)->inputs_[0]->path().c_str());
+        printf("\"\n  }");
+
+        first = false;
+      }
+    }
+  }
+
+  puts("\n]");
+  return 0;
+}
+
 int ToolUrtle(Globals* globals, int argc, char** argv) {
   // RLE encoded.
   const char* urtle =
@@ -533,6 +576,8 @@ int ChooseTool(const string& tool_name, const Tool** tool_out) {
       Tool::RUN_AFTER_LOAD, ToolQuery },
     { "targets",  "list targets by their rule or depth in the DAG",
       Tool::RUN_AFTER_LOAD, ToolTargets },
+    { "compdb",  "dump JSON compilation database to stdout",
+      Tool::RUN_AFTER_LOAD, ToolCompilationDatabase },
     { "urtle", NULL,
       Tool::RUN_AFTER_FLAGS, ToolUrtle },
     { NULL, NULL, Tool::RUN_AFTER_FLAGS, NULL }