From 818aefcecf3cca986c971cd236bd7b77337db955 Mon Sep 17 00:00:00 2001 From: Doug Johnston Date: Thu, 6 Apr 2017 10:25:56 -0700 Subject: [PATCH 1/3] make use of clang compilation database See: https://clang.llvm.org/docs/JSONCompilationDatabase.html --- CMakeLists.txt | 9 +++++++-- src/CMakeLists.txt | 13 +++++++++++++ src/clangparser.cpp | 35 ++++++++++++++++++++++++++++++++++- src/config.xml | 14 ++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6127de2a9ba..e3c3d0839e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,14 +35,19 @@ set(clang "0" CACHE INTERNAL "used in settings.h") if (use_sqlite3) set(sqlite3 "1" CACHE INTERNAL "used in settings.h") endif() + +set(MACOS_VERSION_MIN 10.5) if (use_libclang) set(clang "1" CACHE INTERNAL "used in settings.h") find_package(LibClang REQUIRED) + if (${CMAKE_SYSTEM} MATCHES "Darwin") + set(MACOS_VERSION_MIN 10.11) + endif() endif() if (${CMAKE_SYSTEM} MATCHES "Darwin") - set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=10.5 ${CMAKE_CXX_FLAGS}") - set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=10.5 ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_C_FLAGS}") find_library(CORESERVICES_LIB CoreServices) set(EXTRA_LIBS ${CORESERVICES_LIB}) endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 08c84395320..df76cb01fd0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -244,6 +244,19 @@ add_library(_doxygen STATIC ) add_executable(doxygen main.cpp) + +if (use_libclang) + find_package(LLVM REQUIRED CONFIG) + find_package(Clang REQUIRED CONFIG) + target_compile_features(_doxygen PRIVATE cxx_alignof) + target_compile_options(_doxygen PRIVATE -stdlib=libc++ -std=c++11) + target_compile_features(doxygen PRIVATE cxx_alignof) + target_compile_options(doxygen PRIVATE -stdlib=libc++ -std=c++11) + llvm_map_components_to_libnames(llvm_libs support core option) + target_compile_definitions(doxygen PRIVATE ${LLVM_DEFINITIONS}) + set(CLANG_LIBS ${llvm_libs} ${CLANG_LIBS} clangTooling) +endif() + target_link_libraries(doxygen _doxygen doxycfg diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 67e754b6ac8..77151d6e7dc 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -4,6 +4,7 @@ #if USE_LIBCLANG #include +#include "clang/Tooling/Tooling.h" #include #include #include "message.h" @@ -160,15 +161,46 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); static QStrList &includePath = Config_getList(INCLUDE_PATH); static QStrList clangOptions = Config_getList(CLANG_OPTIONS); + static QCString clangCompileDatabase = Config_getList(CLANG_COMPILATION_DATABASE_PATH); if (!clangAssistedParsing) return; //printf("ClangParser::start(%s)\n",fileName); p->fileName = fileName; p->index = clang_createIndex(0, 0); p->curLine = 1; p->curToken = 0; - char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count())); QDictIterator di(Doxygen::inputPaths); int argc=0; + std::string error; + // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html) + // this only needs to be loaded once, and could be refactored to a higher level function + static std::unique_ptr db = + clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error); + int clang_option_len = 0; + std::vector command; + if (strcmp(clangCompileDatabase, "0") != 0) { + if (db == nullptr) { + // user specified a path, but DB file was not found + err("%s using clang compilation database path of: \"%s\"\n", error.c_str(), + clangCompileDatabase.data()); + } else { + // check if the file we are parsing is in the DB + command = db->getCompileCommands(fileName); + if (!command.empty() ) { + // it's possible to have multiple entries for the same file, so use the last entry + clang_option_len = command[command.size()-1].CommandLine.size(); + } + } + } + char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()+clang_option_len)); + if (!command.empty() ) { + std::vector options = command[command.size()-1].CommandLine; + // copy each compiler option used from the database. Skip the first which is compiler exe. + for (auto option = options.begin()+1; option != options.end(); option++) { + argv[argc++] = strdup(option->c_str()); + } + // this extra addition to argv is accounted for as we are skipping the first entry in + argv[argc++]=strdup("-w"); // finally, turn off warnings. + } else { // add include paths for input files for (di.toFirst();di.current();++di,++argc) { @@ -230,6 +262,7 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit) // provide the input and and its dependencies as unsaved files so we can // pass the filtered versions argv[argc++]=strdup(fileName); + } static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); //printf("source %s ----------\n%s\n-------------\n\n", // fileName,p->source.data()); diff --git a/src/config.xml b/src/config.xml index 2a7cbeb580c..55ee0b17554 100644 --- a/src/config.xml +++ b/src/config.xml @@ -1637,6 +1637,20 @@ to disable this feature. ]]> +