Only include extra headers if they are not already in the search path

This commit adds additional logic to only add the headers of LLVM, clang and
rapidjson if they are not already in the compiler's default search path.

The issue was, that adding the same folder via:
target_include_directories(tgt SYSTEM ${foo})
results in the following invocation of gcc:
gcc -isystem $foo ...
which causes issues with libstdc++ shipped by gcc9. libstdc++ makes use of
 #include_next for some internal trickery, but that changes the way headers are
resolved and causes compilation failures because standard headers are now
suddenly missing.

With this commit we now check each of the extra include directories if they are
already in the compiler's search path. If they are, we don't add them and
circumvent this issue.
This commit is contained in:
Dan Čermák 2019-06-27 12:19:11 +02:00
parent 2eefca2ab8
commit 5b0cc0d803
No known key found for this signature in database
GPG Key ID: E632C3380610D1C5

View File

@ -144,8 +144,7 @@ set_property(SOURCE src/utils.cc APPEND PROPERTY COMPILE_DEFINITIONS
### Includes
target_include_directories(ccls PRIVATE src)
target_include_directories(ccls SYSTEM PRIVATE
third_party ${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS})
target_include_directories(ccls SYSTEM PRIVATE third_party)
if(USE_SYSTEM_RAPIDJSON)
find_package(RapidJSON QUIET)
@ -153,7 +152,33 @@ endif()
if(NOT RapidJSON_FOUND)
set(RapidJSON_INCLUDE_DIRS third_party/rapidjson/include)
endif()
target_include_directories(ccls SYSTEM PRIVATE ${RapidJSON_INCLUDE_DIRS})
# only add the include directories for LLVM, clang & rapidjson if they aren't in
# the default list of include directories (these are stored by cmake in
# CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES)
#
# Adding the same include directory twice with SYSTEM results these being
# included as -isystem, which causes issues with libstdc++ from gcc9 with their
# usage of #include_next<>
# see also: https://github.com/MaskRay/ccls/pull/417
foreach(include_dir
${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS} ${RapidJSON_INCLUDE_DIRS})
# rapidjson's include dir is a relative path => normalize it
get_filename_component(include_dir_realpath ${include_dir} REALPATH)
set(dir_already_included FALSE)
foreach(cxx_include_dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
if("${cxx_include_dir}" STREQUAL "${include_dir_realpath}")
set(dir_already_included TRUE)
endif()
endforeach()
if(NOT "${dir_already_included}")
target_include_directories(ccls SYSTEM PRIVATE ${include_dir})
endif()
endforeach()
### Install