[cfe-commits] r159484 - in /cfe/trunk: include/clang-c/CXCompilationDatabase.h test/Index/compile_commands.json tools/c-index-test/c-index-test.c tools/libclang/CIndexCompilationDB.cpp tools/libclang/CMakeLists.txt tools/libclang/libclang.exports

Arnaud A. de Grandmaison arnaud.adegm at gmail.com
Sat Jun 30 04:27:57 PDT 2012


Author: aadg
Date: Sat Jun 30 06:27:57 2012
New Revision: 159484

URL: http://llvm.org/viewvc/llvm-project?rev=159484&view=rev
Log:
[libclang] add CompilationDatabase support

Added:
    cfe/trunk/include/clang-c/CXCompilationDatabase.h
    cfe/trunk/test/Index/compile_commands.json
    cfe/trunk/tools/libclang/CIndexCompilationDB.cpp
Modified:
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CMakeLists.txt
    cfe/trunk/tools/libclang/libclang.exports

Added: cfe/trunk/include/clang-c/CXCompilationDatabase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/CXCompilationDatabase.h?rev=159484&view=auto
==============================================================================
--- cfe/trunk/include/clang-c/CXCompilationDatabase.h (added)
+++ cfe/trunk/include/clang-c/CXCompilationDatabase.h Sat Jun 30 06:27:57 2012
@@ -0,0 +1,143 @@
+/*===-- clang-c/CXCompilationDatabase.h - Compilation database  ---*- C -*-===*\
+|*                                                                            *|
+|*                     The LLVM Compiler Infrastructure                       *|
+|*                                                                            *|
+|* This file is distributed under the University of Illinois Open Source      *|
+|* License. See LICENSE.TXT for details.                                      *|
+|*                                                                            *|
+|*===----------------------------------------------------------------------===*|
+|*                                                                            *|
+|* This header provides a public inferface to use CompilationDatabase without *|
+|* the full Clang C++ API.                                                    *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef CLANG_CXCOMPILATIONDATABASE_H
+#define CLANG_CXCOMPILATIONDATABASE_H
+
+#include "clang-c/Platform.h"
+#include "clang-c/CXString.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \defgroup COMPILATIONDB CompilationDatabase functions
+ * \ingroup CINDEX
+ *
+ * @{
+ */
+
+/**
+ * \brief Represents clang::tooling::CompilationDatabase
+ *
+ * Must be freed by \c clang_tooling_CompilationDatabase_dispose
+ */
+typedef void * CXCompilationDatabase;
+
+/**
+ * \brief Contains the results of a search in the compilation database
+ *
+ * When searching for the compile command for a file, the compilation db can
+ * return several commands, as the file may have been compiled with
+ * different options in different places of the project. This choice of compile
+ * commands is wrapped in this opaque data structure. It must be freed by
+ * \c clang_tooling_CompileCommands_dispose.
+ */
+typedef void * CXCompileCommands;
+
+/**
+ * \brief Represents the command line invocation to compile a specific file.
+ */
+typedef void * CXCompileCommand;
+
+/**
+ * \brief Error codes for Compilation Database
+ */
+typedef enum  {
+  /*
+   * \brief No error occured
+   */
+  CXCompilationDatabase_NoError = 0,
+
+  /*
+   * \brief Database can not be loaded
+   */
+  CXCompilationDatabase_CanNotLoadDatabase = 1
+
+} CXCompilationDatabase_Error;
+
+/**
+ * \brief Creates a compilation database from the database found in directory
+ * buildDir. It must be freed by \c clang_tooling_CompilationDatabase_dispose.
+ */
+CINDEX_LINKAGE CXCompilationDatabase
+clang_tooling_CompilationDatabase_fromDirectory(
+  const char *BuildDir,
+  CXCompilationDatabase_Error *ErrorCode);
+
+/**
+ * \brief Free the given compilation database
+ */
+CINDEX_LINKAGE void
+clang_tooling_CompilationDatabase_dispose(CXCompilationDatabase);
+
+/**
+ * \brief Find the compile commands used for a file. The compile commands
+ * must be freed by \c clang_tooling_CompileCommands_dispose.
+ */
+CINDEX_LINKAGE CXCompileCommands
+clang_tooling_CompilationDatabase_getCompileCommands(
+  CXCompilationDatabase,
+  const char *CompleteFileName);
+
+/**
+ * \brief Free the given CompileCommands
+ */
+CINDEX_LINKAGE void clang_tooling_CompileCommands_dispose(CXCompileCommands);
+
+/**
+ * \brief Get the number of CompileCommand we have for a file
+ */
+CINDEX_LINKAGE unsigned
+clang_tooling_CompileCommands_getSize(CXCompileCommands);
+
+/**
+ * \brief Get the I'th CompileCommand for a file
+ *
+ * Note : 0 <= i < clang_tooling_CompileCommands_getSize(CXCompileCommands)
+ */
+CINDEX_LINKAGE CXCompileCommand
+clang_tooling_CompileCommands_getCommand(CXCompileCommands, unsigned I);
+
+/**
+ * \brief Get the working directory where the CompileCommand was executed from
+ */
+CINDEX_LINKAGE CXString
+clang_tooling_CompileCommand_getDirectory(CXCompileCommand);
+
+/**
+ * \brief Get the number of arguments in the compiler invocation.
+ *
+ */
+CINDEX_LINKAGE unsigned
+clang_tooling_CompileCommand_getNumArgs(CXCompileCommand);
+
+/**
+ * \brief Get the I'th argument value in the compiler invocations
+ *
+ * Invariant :
+ *  - argument 0 is the compiler executable
+ */
+CINDEX_LINKAGE CXString
+clang_tooling_CompileCommand_getArg(CXCompileCommand, unsigned I);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+

Added: cfe/trunk/test/Index/compile_commands.json
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/compile_commands.json?rev=159484&view=auto
==============================================================================
--- cfe/trunk/test/Index/compile_commands.json (added)
+++ cfe/trunk/test/Index/compile_commands.json Sat Jun 30 06:27:57 2012
@@ -0,0 +1,27 @@
+[
+{
+  "directory": "/home/john.doe/MyProject",
+  "command": "clang++  -o project.o -c /home/john.doe/MyProject/project.cpp",
+  "file": "/home/john.doe/MyProject/project.cpp"
+},
+{
+  "directory": "/home/john.doe/MyProjectA",
+  "command": "clang++ -o project2.o -c /home/john.doe/MyProject/project2.cpp",
+  "file": "/home/john.doe/MyProject/project2.cpp"
+},
+{
+  "directory": "/home/john.doe/MyProjectB",
+  "command": "clang++  -DFEATURE=1 -o project2-feature.o -c /home/john.doe/MyProject/project2.cpp",
+  "file": "/home/john.doe/MyProject/project2.cpp"
+}
+]
+# RUN: c-index-test -compilation-db %s
+# RUN: c-index-test -compilation-db lookup file_does_not_exists.cpp %s | FileCheck -check-prefix=FILE-NOT-FOUND %s
+# FILE-NOT-FOUND: file file_does_not_exists.cpp not found in compilation db
+
+# RUN: c-index-test -compilation-db lookup /home/john.doe/MyProject/project.cpp %s | FileCheck -check-prefix=FILE-1-CMD %s
+# FILE-1-CMD: workdir:'/home/john.doe/MyProject' cmdline:'clang++  -o project.o -c /home/john.doe/MyProject/project.cpp'
+
+# RUN: c-index-test -compilation-db lookup /home/john.doe/MyProject/project2.cpp %s | FileCheck -check-prefix=FILE-2-CMD %s
+# FILE-2-CMD: workdir:'/home/john.doe/MyProjectA' cmdline:'clang++ -o project2.o -c /home/john.doe/MyProject/project2.cpp'
+# FILE-2-CMD: workdir:'/home/john.doe/MyProjectB' cmdline:'clang++ -DFEATURE=1 -o project2-feature.o -c /home/john.doe/MyProject/project2.cpp'

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=159484&r1=159483&r2=159484&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Sat Jun 30 06:27:57 2012
@@ -1,6 +1,7 @@
 /* c-index-test.c */
 
 #include "clang-c/Index.h"
+#include "clang-c/CXCompilationDatabase.h"
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -25,8 +26,25 @@
 
     return((char*)path);
 }
+char *dirname(char* path)
+{
+    char* base1 = (char*)strrchr(path, '/');
+    char* base2 = (char*)strrchr(path, '\\');
+    if (base1 && base2)
+        if (base1 > base2)
+          *base1 = 0;
+        else
+          *base2 = 0;
+    else if (base1)
+        *base1 = 0
+    else if (base2)
+        *base2 = 0
+
+    return path;
+}
 #else
 extern char *basename(const char *);
+extern char *dirname(char *);
 #endif
 
 /** \brief Return the default parsing options. */
@@ -2361,6 +2379,89 @@
   return errorCode;
 }
 
+static int
+perform_test_compilation_db(const char *database, int argc, const char **argv) {
+  CXCompilationDatabase db;
+  CXCompileCommands CCmds;
+  CXCompileCommand CCmd;
+  CXCompilationDatabase_Error ec;
+  CXString wd;
+  CXString arg;
+  int errorCode = 0;
+  char *tmp;
+  unsigned len;
+  char *buildDir;
+  int i, j, a, numCmds, numArgs;
+
+  len = strlen(database);
+  tmp = (char *) malloc(len+1);
+  memcpy(tmp, database, len+1);
+  buildDir = dirname(tmp);
+
+  db = clang_tooling_CompilationDatabase_fromDirectory(buildDir, &ec);
+
+  if (db) {
+
+    if (ec!=CXCompilationDatabase_NoError) {
+      printf("unexpected error %d code while loading compilation database\n", ec);
+      errorCode = -1;
+      goto cdb_end;
+    }
+
+    for (i=0; i<argc && errorCode==0; ) {
+      if (strcmp(argv[i],"lookup")==0){
+        CCmds = clang_tooling_CompilationDatabase_getCompileCommands(db, argv[i+1]);
+
+        if (!CCmds) {
+          printf("file %s not found in compilation db\n", argv[i+1]);
+          errorCode = -1;
+          break;
+        }
+
+        numCmds = clang_tooling_CompileCommands_getSize(CCmds);
+
+        if (numCmds==0) {
+          fprintf(stderr, "should not get an empty compileCommand set for file"
+                          " '%s'\n", argv[i+1]);
+          errorCode = -1;
+          break;
+        }
+
+        for (j=0; j<numCmds; ++j) {
+          CCmd = clang_tooling_CompileCommands_getCommand(CCmds, j);
+
+          wd = clang_tooling_CompileCommand_getDirectory(CCmd);
+          printf("workdir:'%s'", clang_getCString(wd));
+          clang_disposeString(wd);
+
+          printf(" cmdline:'");
+          numArgs = clang_tooling_CompileCommand_getNumArgs(CCmd);
+          for (a=0; a<numArgs; ++a) {
+            if (a) printf(" ");
+            arg = clang_tooling_CompileCommand_getArg(CCmd, a);
+            printf("%s", clang_getCString(arg));
+            clang_disposeString(arg);
+          }
+          printf("'\n");
+        }
+
+        clang_tooling_CompileCommands_dispose(CCmds);
+
+        i += 2;
+      }
+    }
+    clang_tooling_CompilationDatabase_dispose(db);
+  } else {
+    printf("database loading failed with error code %d.\n", ec);
+    errorCode = -1;
+  }
+
+cdb_end:
+  free(tmp);
+
+  return errorCode;
+}
+
 /******************************************************************************/
 /* USR printing.                                                              */
 /******************************************************************************/
@@ -2801,6 +2902,8 @@
     "       c-index-test -print-usr-file <file>\n"
     "       c-index-test -write-pch <file> <compiler arguments>\n");
   fprintf(stderr,
+    "       c-index-test -compilation-db [lookup <filename>] database\n");
+  fprintf(stderr,
     "       c-index-test -read-diagnostics <file>\n\n");
   fprintf(stderr,
     " <symbol filter> values:\n%s",
@@ -2886,7 +2989,9 @@
     return print_usrs_file(argv[2]);
   else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0)
     return write_pch_file(argv[2], argc - 3, argv + 3);
-           
+  else if (argc > 2 && strcmp(argv[1], "-compilation-db") == 0)
+    return perform_test_compilation_db(argv[argc-1], argc - 3, argv + 2);
+
   print_usage();
   return 1;
 }

Added: cfe/trunk/tools/libclang/CIndexCompilationDB.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCompilationDB.cpp?rev=159484&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/CIndexCompilationDB.cpp (added)
+++ cfe/trunk/tools/libclang/CIndexCompilationDB.cpp Sat Jun 30 06:27:57 2012
@@ -0,0 +1,130 @@
+#include "clang-c/CXCompilationDatabase.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "CXString.h"
+
+using namespace clang;
+using namespace clang::tooling;
+using namespace clang::cxstring;
+
+extern "C" {
+
+// FIXME: do something more usefull with the error message
+CXCompilationDatabase
+clang_tooling_CompilationDatabase_fromDirectory(
+  const char *BuildDir,
+  CXCompilationDatabase_Error *ErrorCode)
+{
+  std::string ErrorMsg;
+  CXCompilationDatabase_Error Err = CXCompilationDatabase_NoError;
+
+  CompilationDatabase *db = CompilationDatabase::loadFromDirectory(BuildDir,
+                                                                   ErrorMsg);
+
+  if (!db) {
+    fprintf(stderr, "LIBCLANG TOOLING ERROR: %s\n", ErrorMsg.c_str());
+    Err = CXCompilationDatabase_CanNotLoadDatabase;
+  }
+
+  if (ErrorCode)
+    *ErrorCode = Err;
+
+  return db;
+}
+
+void
+clang_tooling_CompilationDatabase_dispose(CXCompilationDatabase CDb)
+{
+  delete static_cast<CompilationDatabase *>(CDb);
+}
+
+struct AllocatedCXCompileCommands
+{
+  std::vector<CompileCommand> CCmd;
+
+  AllocatedCXCompileCommands(const std::vector<CompileCommand>& Cmd)
+    : CCmd(Cmd)
+  { }
+};
+
+CXCompileCommands
+clang_tooling_CompilationDatabase_getCompileCommands(CXCompilationDatabase CDb,
+                                 const char *CompleteFileName)
+{
+  if (CompilationDatabase *db = static_cast<CompilationDatabase *>(CDb)) {
+    const std::vector<CompileCommand>
+      CCmd(db->getCompileCommands(CompleteFileName));
+    if (!CCmd.empty())
+      return new AllocatedCXCompileCommands( CCmd );
+  }
+
+  return 0;
+}
+
+void
+clang_tooling_CompileCommands_dispose(CXCompileCommands Cmds)
+{
+  delete static_cast<AllocatedCXCompileCommands *>(Cmds);
+}
+
+unsigned
+clang_tooling_CompileCommands_getSize(CXCompileCommands Cmds)
+{
+  if (!Cmds)
+    return 0;
+
+  AllocatedCXCompileCommands *ACC =
+    static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+  return ACC->CCmd.size();
+}
+
+CXCompileCommand
+clang_tooling_CompileCommands_getCommand(CXCompileCommands Cmds, unsigned I)
+{
+  if (!Cmds)
+    return 0;
+
+  AllocatedCXCompileCommands *ACC =
+    static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+  if (I >= ACC->CCmd.size())
+    return 0;
+
+  return &ACC->CCmd[I];
+}
+
+CXString
+clang_tooling_CompileCommand_getDirectory(CXCompileCommand CCmd)
+{
+  if (!CCmd)
+    return createCXString((const char*)NULL);
+
+  CompileCommand *cmd = static_cast<CompileCommand *>(CCmd);
+  return createCXString(cmd->Directory);
+}
+
+unsigned
+clang_tooling_CompileCommand_getNumArgs(CXCompileCommand CCmd)
+{
+  if (!CCmd)
+    return 0;
+
+  return static_cast<CompileCommand *>(CCmd)->CommandLine.size();
+}
+
+CXString
+clang_tooling_CompileCommand_getArg(CXCompileCommand CCmd, unsigned Arg)
+{
+  if (!CCmd)
+    return createCXString((const char*)NULL);
+
+  CompileCommand *Cmd = static_cast<CompileCommand *>(CCmd);
+
+  if (Arg >= Cmd->CommandLine.size())
+    return createCXString((const char*)NULL);
+
+  return createCXString(Cmd->CommandLine[Arg]);
+}
+
+
+} // end: extern "C"

Modified: cfe/trunk/tools/libclang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=159484&r1=159483&r2=159484&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CMakeLists.txt (original)
+++ cfe/trunk/tools/libclang/CMakeLists.txt Sat Jun 30 06:27:57 2012
@@ -8,6 +8,7 @@
   CIndex.cpp
   CIndexCXX.cpp
   CIndexCodeCompletion.cpp
+  CIndexCompilationDB.cpp
   CIndexDiagnostic.cpp
   CIndexDiagnostic.h
   CIndexHigh.cpp
@@ -47,6 +48,7 @@
   clangEdit
   clangAST
   clangLex
+  clangTooling
   clangBasic
   )
 

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=159484&r1=159483&r2=159484&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Sat Jun 30 06:27:57 2012
@@ -204,5 +204,14 @@
 clang_sortCodeCompletionResults
 clang_toggleCrashRecovery
 clang_tokenize
+clang_tooling_CompilationDatabase_fromDirectory
+clang_tooling_CompilationDatabase_dispose
+clang_tooling_CompilationDatabase_getCompileCommands
+clang_tooling_CompileCommands_dispose
+clang_tooling_CompileCommands_getSize
+clang_tooling_CompileCommands_getCommand
+clang_tooling_CompileCommand_getDirectory
+clang_tooling_CompileCommand_getNumArgs
+clang_tooling_CompileCommand_getArg
 clang_visitChildren
 clang_visitChildrenWithBlock





More information about the cfe-commits mailing list