mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-21 23:25:07 +00:00
Use clang+llvm C++ in cmake; parse args with clang driver
This commit is contained in:
parent
b349983e13
commit
c269876593
@ -86,10 +86,12 @@ if(NOT SYSTEM_CLANG)
|
||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang AND CLANG_USE_BUNDLED_LIBC++)
|
||||
message(STATUS "Using bundled libc++")
|
||||
target_compile_options(ccls PRIVATE -nostdinc++ -cxx-isystem ${CLANG_ROOT}/include/c++/v1)
|
||||
target_link_libraries(ccls PRIVATE -stdlib=libc++ -L${CLANG_ROOT}/lib -lc++experimental)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
||||
# Don't use -stdlib=libc++ because while ccls is linked with libc++, bundled clang+llvm require libstdc++
|
||||
target_link_libraries(ccls PRIVATE -L${CLANG_ROOT}/lib c++ c++experimental c++abi)
|
||||
else()
|
||||
# FreeBSD uses system libcxxrt.a and does not need libc++abi.
|
||||
target_link_libraries(ccls PRIVATE c++abi)
|
||||
target_link_libraries(ccls PRIVATE -stdlib=libc++ -L${CLANG_ROOT}/lib c++experimental)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -101,7 +103,11 @@ endif()
|
||||
|
||||
# See cmake/FindClang.cmake
|
||||
find_package(Clang ${CLANG_VERSION} REQUIRED)
|
||||
find_package(Curses REQUIRED)
|
||||
target_link_libraries(ccls PRIVATE Clang::Clang)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
||||
target_link_libraries(ccls PRIVATE Clang::Clang ${CURSES_LIBRARIES})
|
||||
endif()
|
||||
|
||||
# Enable threading support
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
@ -188,27 +194,6 @@ endif()
|
||||
file(GLOB SOURCES src/*.cc src/*.h src/serializers/*.cc src/serializers/*.h
|
||||
src/messages/*.h src/messages/*.cc)
|
||||
|
||||
if(Clang_FORMAT AND ${Clang_VERSION} STREQUAL 6.0.0)
|
||||
add_custom_target(format
|
||||
COMMAND ${Clang_FORMAT} -i ${SOURCES}
|
||||
# .clang-format is located in the ccls root project dir
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Running clang-format ...")
|
||||
else()
|
||||
# Set error message depending on which condition was false
|
||||
if (NOT Clang_FORMAT)
|
||||
set(Clang_FORMAT_ERROR "Error: clang-format executable not found")
|
||||
elseif(NOT ${Clang_VERSION} STREQUAL 6.0.0)
|
||||
set(Clang_FORMAT_ERROR "Error: clang-format version does not match \
|
||||
6.0.0. Due to differences in clang-format output between versions we only \
|
||||
support clang-format 6.0.0")
|
||||
endif()
|
||||
|
||||
add_custom_target(format
|
||||
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red --bold
|
||||
${Clang_FORMAT_ERROR})
|
||||
endif()
|
||||
|
||||
### Sources
|
||||
|
||||
target_sources(ccls PRIVATE third_party/siphash.cc)
|
||||
|
@ -8,7 +8,6 @@
|
||||
#
|
||||
# Clang_FOUND - True if headers and requested libraries were found
|
||||
# Clang_EXECUTABLE - Clang executable
|
||||
# Clang_FORMAT - Clang-format executable
|
||||
# Clang_RESOURCE_DIR - Clang resource directory
|
||||
# Clang_VERSION - Clang version as reported by Clang executable
|
||||
#
|
||||
@ -19,7 +18,6 @@
|
||||
# This module reads hints about which libraries to look for and where to find
|
||||
# them from the following variables::
|
||||
#
|
||||
# CLANG_CXX - Search for and add Clang C++ libraries
|
||||
# CLANG_ROOT - If set, only look for Clang components in CLANG_ROOT
|
||||
#
|
||||
# Example to link against Clang target::
|
||||
@ -41,6 +39,11 @@ macro(_Clang_find_library VAR NAME)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(_Clang_find_add_library NAME)
|
||||
_Clang_find_library(${NAME}_LIBRARY ${NAME})
|
||||
list(APPEND _Clang_LIBRARIES ${${NAME}_LIBRARY})
|
||||
endmacro()
|
||||
|
||||
macro(_Clang_find_path VAR INCLUDE_FILE)
|
||||
if (CLANG_ROOT)
|
||||
find_path(${VAR} ${INCLUDE_FILE}
|
||||
@ -59,45 +62,22 @@ macro(_Clang_find_program VAR NAME)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Macro to avoid duplicating logic for each Clang C++ library
|
||||
macro(_Clang_find_and_add_cxx_lib NAME INCLUDE_FILE)
|
||||
# Find library
|
||||
_Clang_find_library(Clang_${NAME}_LIBRARY ${NAME})
|
||||
list(APPEND _Clang_REQUIRED_VARS Clang_${NAME}_LIBRARY)
|
||||
list(APPEND _Clang_CXX_LIBRARIES ${Clang_${NAME}_LIBRARY})
|
||||
|
||||
# Find corresponding include directory
|
||||
_Clang_find_path(Clang_${NAME}_INCLUDE_DIR ${INCLUDE_FILE})
|
||||
list(APPEND _Clang_REQUIRED_VARS Clang_${NAME}_INCLUDE_DIR)
|
||||
list(APPEND _Clang_CXX_INCLUDE_DIRS ${Clang_${NAME}_INCLUDE_DIR})
|
||||
endmacro()
|
||||
|
||||
### Start
|
||||
|
||||
set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE
|
||||
Clang_RESOURCE_DIR Clang_VERSION)
|
||||
Clang_RESOURCE_DIR Clang_VERSION
|
||||
LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR)
|
||||
|
||||
_Clang_find_library(Clang_LIBRARY clang)
|
||||
_Clang_find_add_library(clangDriver)
|
||||
_Clang_find_add_library(LLVMOption)
|
||||
_Clang_find_add_library(LLVMSupport)
|
||||
_Clang_find_add_library(LLVMDemangle)
|
||||
_Clang_find_path(Clang_INCLUDE_DIR clang-c/Index.h)
|
||||
_Clang_find_path(Clang_BUILD_INCLUDE_DIR clang/Driver/Options.inc)
|
||||
_Clang_find_path(LLVM_INCLUDE_DIR llvm/PassInfo.h)
|
||||
_Clang_find_path(LLVM_BUILD_INCLUDE_DIR llvm/Config/llvm-config.h)
|
||||
|
||||
if(CLANG_CXX)
|
||||
# The order is derived by topological sorting LINK_LIBS in
|
||||
# clang/lib/*/CMakeLists.txt
|
||||
_Clang_find_and_add_cxx_lib(clangFormat clang/Format/Format.h)
|
||||
_Clang_find_and_add_cxx_lib(clangToolingCore clang/Tooling/Core/Diagnostic.h)
|
||||
_Clang_find_and_add_cxx_lib(clangRewrite clang/Rewrite/Core/Rewriter.h)
|
||||
_Clang_find_and_add_cxx_lib(clangAST clang/AST/AST.h)
|
||||
_Clang_find_and_add_cxx_lib(clangLex clang/Lex/Lexer.h)
|
||||
_Clang_find_and_add_cxx_lib(clangBasic clang/Basic/ABI.h)
|
||||
|
||||
# The order is derived from llvm-config --libs core
|
||||
_Clang_find_and_add_cxx_lib(LLVMCore llvm/Pass.h)
|
||||
_Clang_find_and_add_cxx_lib(LLVMBinaryFormat llvm/BinaryFormat/Dwarf.h)
|
||||
_Clang_find_and_add_cxx_lib(LLVMSupport llvm/Support/Error.h)
|
||||
_Clang_find_and_add_cxx_lib(LLVMDemangle llvm/Demangle/Demangle.h)
|
||||
endif()
|
||||
|
||||
_Clang_find_program(Clang_FORMAT clang-format)
|
||||
_Clang_find_program(Clang_EXECUTABLE clang)
|
||||
if(Clang_EXECUTABLE)
|
||||
# Find Clang resource directory with Clang executable
|
||||
@ -127,12 +107,10 @@ find_package_handle_standard_args(Clang
|
||||
)
|
||||
|
||||
if(Clang_FOUND AND NOT TARGET Clang::Clang)
|
||||
set(_Clang_LIBRARIES ${Clang_LIBRARY} ${_Clang_CXX_LIBRARIES})
|
||||
set(_Clang_INCLUDE_DIRS ${Clang_INCLUDE_DIR} ${_Clang_CXX_INCLUDE_DIRS})
|
||||
add_library(Clang::Clang UNKNOWN IMPORTED)
|
||||
set_target_properties(Clang::Clang PROPERTIES
|
||||
IMPORTED_LOCATION ${Clang_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Clang_INCLUDE_DIR};${Clang_BUILD_INCLUDE_DIR};${LLVM_INCLUDE_DIR};${LLVM_BUILD_INCLUDE_DIR}")
|
||||
|
||||
add_library(Clang::Clang INTERFACE IMPORTED)
|
||||
set_property(TARGET Clang::Clang PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${_Clang_LIBRARIES})
|
||||
set_property(TARGET Clang::Clang PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${_Clang_INCLUDE_DIRS})
|
||||
set_property(TARGET Clang::Clang PROPERTY INTERFACE_LINK_LIBRARIES ${_Clang_LIBRARIES})
|
||||
endif()
|
||||
|
@ -517,7 +517,8 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
||||
for (int i = 0; i < g_config->index.threads; i++) {
|
||||
std::thread([=]() {
|
||||
g_thread_id = i + 1;
|
||||
SetThreadName("indexer" + std::to_string(i));
|
||||
std::string name = "indexer" + std::to_string(i);
|
||||
SetThreadName(name.c_str());
|
||||
Indexer_Main(diag_engine, vfs, import_pipeline_status, project,
|
||||
working_files, waiter);
|
||||
}).detach();
|
||||
|
@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
void PlatformInit();
|
||||
@ -12,9 +11,7 @@ void PlatformInit();
|
||||
std::string GetExecutablePath();
|
||||
std::string NormalizePath(const std::string& path);
|
||||
|
||||
void SetThreadName(const std::string& thread_name);
|
||||
|
||||
std::optional<int64_t> GetLastModificationTime(const std::string& absolute_path);
|
||||
void SetThreadName(const char* name);
|
||||
|
||||
// Free any unused memory and return it to the system.
|
||||
void FreeUnusedMemory();
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include <llvm/ADT/Twine.h>
|
||||
#include <llvm/Support/Threading.h>
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
#include "platform.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "loguru.hpp"
|
||||
#include <loguru.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#if defined(__FreeBSD__)
|
||||
@ -155,17 +158,6 @@ std::string NormalizePath(const std::string& path) {
|
||||
return resolved ? *resolved : path;
|
||||
}
|
||||
|
||||
void SetThreadName(const std::string& thread_name) {
|
||||
loguru::set_thread_name(thread_name.c_str());
|
||||
#if defined(__APPLE__)
|
||||
pthread_setname_np(thread_name.c_str());
|
||||
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
pthread_set_name_np(pthread_self(), thread_name.c_str());
|
||||
#elif defined(__linux__)
|
||||
pthread_setname_np(pthread_self(), thread_name.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void FreeUnusedMemory() {
|
||||
#if defined(__GLIBC__)
|
||||
malloc_trim(0);
|
||||
@ -225,3 +217,8 @@ std::string GetExternalCommandOutput(const std::vector<std::string>& command,
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SetThreadName(const char* name) {
|
||||
loguru::set_thread_name(name);
|
||||
llvm::set_thread_name(name);
|
||||
}
|
||||
|
@ -49,36 +49,6 @@ std::string NormalizePath(const std::string& path) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
#pragma pack(push, 8)
|
||||
typedef struct tagTHREADNAME_INFO {
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
void SetThreadName(const std::string& thread_name) {
|
||||
loguru::set_thread_name(thread_name.c_str());
|
||||
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = thread_name.c_str();
|
||||
info.dwThreadID = (DWORD)-1;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try {
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
|
||||
(ULONG_PTR*)&info);
|
||||
#ifdef _MSC_VER
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
#else
|
||||
} catch (...) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void FreeUnusedMemory() {}
|
||||
|
||||
// TODO Wait for debugger to attach
|
||||
|
193
src/project.cc
193
src/project.cc
@ -12,6 +12,14 @@
|
||||
#include "utils.h"
|
||||
#include "working_files.h"
|
||||
|
||||
#include <clang/Driver/Options.h>
|
||||
#include <llvm/ADT/ArrayRef.h>
|
||||
#include <llvm/Option/ArgList.h>
|
||||
#include <llvm/Option/OptTable.h>
|
||||
using namespace clang;
|
||||
using namespace llvm;
|
||||
using namespace llvm::opt;
|
||||
|
||||
#include <clang-c/CXCompilationDatabase.h>
|
||||
#include <doctest/doctest.h>
|
||||
#include <rapidjson/writer.h>
|
||||
@ -52,45 +60,13 @@ struct ProjectConfig {
|
||||
ProjectMode mode = ProjectMode::CompileCommandsJson;
|
||||
};
|
||||
|
||||
// TODO: See
|
||||
// https://github.com/Valloric/ycmd/blob/master/ycmd/completers/cpp/flags.py.
|
||||
// Flags '-include' and '-include-pch' are blacklisted here cause libclang returns error in case when
|
||||
// precompiled header was generated by a different compiler (even two different builds of same version
|
||||
// of clang for the same platform are incompatible). Note that libclang always generate it's own pch
|
||||
// internally. For details, see https://github.com/Valloric/ycmd/issues/892 .
|
||||
std::vector<std::string> kBlacklistMulti = {
|
||||
"-MF", "-MT", "-MQ", "-o", "--serialize-diagnostics", "-Xclang"};
|
||||
|
||||
// Blacklisted flags which are always removed from the command line.
|
||||
std::vector<std::string> kBlacklist = {
|
||||
"-c", "-MP", "-MD", "-MMD", "--fcolor-diagnostics", "-showIncludes"
|
||||
enum OptionClass {
|
||||
EqOrJoinOrSep,
|
||||
EqOrSep,
|
||||
JoinOrSep,
|
||||
Separate,
|
||||
};
|
||||
|
||||
// Arguments which are followed by a potentially relative path. We need to make
|
||||
// all relative paths absolute, otherwise libclang will not resolve them.
|
||||
std::vector<std::string> kPathArgs = {
|
||||
"-I", "-iquote", "-cxx-isystem", "-isystem", "--sysroot=",
|
||||
"-isysroot", "-gcc-toolchain", "-include-pch", "-iframework",
|
||||
"-F", "-imacros", "-include", "/I",
|
||||
"-idirafter"};
|
||||
|
||||
// Arguments which always require an absolute path, ie, clang -working-directory
|
||||
// does not work as expected. Argument processing assumes that this is a subset
|
||||
// of kPathArgs.
|
||||
std::vector<std::string> kNormalizePathArgs = {"--sysroot="};
|
||||
|
||||
// Arguments whose path arguments should be injected into include dir lookup
|
||||
// for #include completion.
|
||||
std::vector<std::string> kQuoteIncludeArgs = {"-iquote", "-I", "/I"};
|
||||
std::vector<std::string> kAngleIncludeArgs = {"-cxx-isystem", "-isystem", "-I", "/I"};
|
||||
|
||||
bool ShouldAddToQuoteIncludes(const std::string& arg) {
|
||||
return StartsWithAny(arg, kQuoteIncludeArgs);
|
||||
}
|
||||
bool ShouldAddToAngleIncludes(const std::string& arg) {
|
||||
return StartsWithAny(arg, kAngleIncludeArgs);
|
||||
}
|
||||
|
||||
Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
||||
ProjectConfig* config,
|
||||
const CompileCommandsEntry& entry) {
|
||||
@ -136,109 +112,51 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
||||
// Compiler driver.
|
||||
result.args.push_back(args[0]);
|
||||
|
||||
// Add -working-directory if not provided.
|
||||
if (!AnyStartsWith(args, "-working-directory"))
|
||||
result.args.emplace_back("-working-directory=" + entry.directory.string());
|
||||
std::unique_ptr<OptTable> Opts = driver::createDriverOptTable();
|
||||
unsigned MissingArgIndex, MissingArgCount;
|
||||
std::vector<const char*> cargs;
|
||||
for (auto& arg : args)
|
||||
cargs.push_back(arg.c_str());
|
||||
InputArgList Args =
|
||||
Opts->ParseArgs(makeArrayRef(cargs), MissingArgIndex, MissingArgCount,
|
||||
driver::options::CC1Option);
|
||||
|
||||
bool next_flag_is_path = false;
|
||||
bool add_next_flag_to_quote_dirs = false;
|
||||
bool add_next_flag_to_angle_dirs = false;
|
||||
using namespace clang::driver::options;
|
||||
for (const auto* A :
|
||||
Args.filtered(OPT_I, OPT_c_isystem, OPT_cxx_isystem, OPT_isystem))
|
||||
config->angle_dirs.insert(entry.ResolveIfRelative(A->getValue()));
|
||||
for (const auto* A : Args.filtered(OPT_I, OPT_iquote))
|
||||
config->quote_dirs.insert(entry.ResolveIfRelative(A->getValue()));
|
||||
|
||||
// Note that when processing paths, some arguments support multiple forms, ie,
|
||||
// {"-Ifoo"} or {"-I", "foo"}. Support both styles.
|
||||
|
||||
size_t i = 1;
|
||||
result.args.reserve(args.size() + config->extra_flags.size());
|
||||
for (; i < args.size(); ++i) {
|
||||
std::string arg = args[i];
|
||||
|
||||
// Finish processing path for the previous argument, which was a switch.
|
||||
// {"-I", "foo"} style.
|
||||
if (next_flag_is_path) {
|
||||
std::string normalized_arg = entry.ResolveIfRelative(arg);
|
||||
if (add_next_flag_to_quote_dirs)
|
||||
config->quote_dirs.insert(normalized_arg);
|
||||
if (add_next_flag_to_angle_dirs)
|
||||
config->angle_dirs.insert(normalized_arg);
|
||||
if (clang_cl)
|
||||
arg = normalized_arg;
|
||||
|
||||
next_flag_is_path = false;
|
||||
add_next_flag_to_quote_dirs = false;
|
||||
add_next_flag_to_angle_dirs = false;
|
||||
} else {
|
||||
// If blacklist skip.
|
||||
if (StartsWithAny(arg, kBlacklistMulti)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if arg is a path and needs to be updated.
|
||||
for (const std::string& flag_type : kPathArgs) {
|
||||
// {"-I", "foo"} style.
|
||||
if (arg == flag_type) {
|
||||
next_flag_is_path = true;
|
||||
add_next_flag_to_quote_dirs = ShouldAddToQuoteIncludes(arg);
|
||||
add_next_flag_to_angle_dirs = ShouldAddToAngleIncludes(arg);
|
||||
goto done;
|
||||
}
|
||||
|
||||
// {"-Ifoo"} style.
|
||||
if (StartsWith(arg, flag_type)) {
|
||||
std::string path = arg.substr(flag_type.size());
|
||||
assert(!path.empty());
|
||||
path = entry.ResolveIfRelative(path);
|
||||
if (clang_cl || StartsWithAny(arg, kNormalizePathArgs))
|
||||
arg = flag_type + path;
|
||||
if (ShouldAddToQuoteIncludes(flag_type))
|
||||
config->quote_dirs.insert(path);
|
||||
if (ShouldAddToAngleIncludes(flag_type))
|
||||
config->angle_dirs.insert(path);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (StartsWithAny(arg, kBlacklist))
|
||||
continue;
|
||||
|
||||
// This is most likely the file path we will be passing to clang. The
|
||||
// path needs to be absolute, otherwise clang_codeCompleteAt is extremely
|
||||
// slow. See
|
||||
// https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678.
|
||||
if (EndsWith(arg, base_name))
|
||||
arg = entry.ResolveIfRelative(arg);
|
||||
// TODO Exclude .a .o to make link command in compile_commands.json work.
|
||||
// Also, clang_parseTranslationUnit2FullArgv does not seem to accept
|
||||
// multiple source filenames.
|
||||
else if (EndsWith(arg, ".a") || EndsWith(arg, ".o"))
|
||||
continue;
|
||||
for (size_t i = 1; i < args.size(); i++)
|
||||
// This is most likely the file path we will be passing to clang. The
|
||||
// path needs to be absolute, otherwise clang_codeCompleteAt is extremely
|
||||
// slow. See
|
||||
// https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678.
|
||||
if (args[i][0] != '-' && EndsWith(args[i], base_name)) {
|
||||
args[i] = entry.ResolveIfRelative(args[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
done:
|
||||
result.args.push_back(arg);
|
||||
}
|
||||
|
||||
// We don't do any special processing on user-given extra flags.
|
||||
for (const auto& flag : config->extra_flags)
|
||||
result.args.push_back(flag);
|
||||
args.push_back(flag);
|
||||
|
||||
// Add -resource-dir so clang can correctly resolve system includes like
|
||||
// <cstddef>
|
||||
if (!AnyStartsWith(result.args, "-resource-dir"))
|
||||
result.args.push_back("-resource-dir=" + g_config->clang.resourceDir);
|
||||
if (!Args.hasArg(OPT_resource_dir))
|
||||
args.push_back("-resource-dir=" + g_config->clang.resourceDir);
|
||||
if (!Args.hasArg(OPT_working_directory))
|
||||
args.push_back("-working-directory=" + entry.directory.string());
|
||||
|
||||
// There could be a clang version mismatch between what the project uses and
|
||||
// what ccls uses. Make sure we do not emit warnings for mismatched options.
|
||||
if (!AnyStartsWith(result.args, "-Wno-unknown-warning-option"))
|
||||
result.args.push_back("-Wno-unknown-warning-option");
|
||||
args.push_back("-Wno-unknown-warning-option");
|
||||
|
||||
// Using -fparse-all-comments enables documentation in the indexer and in
|
||||
// code completion.
|
||||
if (g_config->index.comments > 1 &&
|
||||
!AnyStartsWith(result.args, "-fparse-all-comments")) {
|
||||
result.args.push_back("-fparse-all-comments");
|
||||
}
|
||||
if (g_config->index.comments > 1)
|
||||
args.push_back("-fparse-all-comments");
|
||||
|
||||
result.args = std::move(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -601,15 +519,15 @@ TEST_SUITE("Project") {
|
||||
CheckFlags(
|
||||
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
||||
/* expected */
|
||||
{"clang", "-working-directory=/dir/", "-lstdc++", "/dir/myfile.cc",
|
||||
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||
"-fparse-all-comments"});
|
||||
{"clang", "-lstdc++", "/dir/myfile.cc",
|
||||
"-resource-dir=/w/resource_dir/", "-working-directory=/dir/",
|
||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||
|
||||
CheckFlags(
|
||||
/* raw */ {"clang.exe"},
|
||||
/* expected */
|
||||
{"clang.exe", "-working-directory=/dir/",
|
||||
"-resource-dir=/w/resource_dir/", "-Wno-unknown-warning-option",
|
||||
{"clang.exe", "-resource-dir=/w/resource_dir/",
|
||||
"-working-directory=/dir/", "-Wno-unknown-warning-option",
|
||||
"-fparse-all-comments"});
|
||||
}
|
||||
|
||||
@ -648,12 +566,13 @@ TEST_SUITE("Project") {
|
||||
#endif
|
||||
|
||||
TEST_CASE("Path in args") {
|
||||
CheckFlags("/home/user", "/home/user/foo/bar.c",
|
||||
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
||||
/* expected */
|
||||
{"cc", "-working-directory=/home/user", "-O0",
|
||||
"/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/",
|
||||
"-Wno-unknown-warning-option", "-fparse-all-comments"});
|
||||
CheckFlags(
|
||||
"/home/user", "/home/user/foo/bar.c",
|
||||
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
||||
/* expected */
|
||||
{"cc", "-O0", "/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/",
|
||||
"-working-directory=/home/user", "-Wno-unknown-warning-option",
|
||||
"-fparse-all-comments"});
|
||||
}
|
||||
|
||||
TEST_CASE("Directory extraction") {
|
||||
|
Loading…
Reference in New Issue
Block a user