include directories not passed to compiler despite INCLUDE_DIRECTORIES

I have a cross compile project. I wish to use include_directories(SYSTEM ${ISYSTEM_PATH}) to add the system include path for all targets (including targets in add_subdirectory), but fails.

The INCLUDE_DIRECTORIES is set correctly for the target, but the path doesn’t show up when invoking the compiler.

# top CMakeLists
cmake_minimum_required(VERSION 3.16)
set(CMAKE_TOOLCHAIN_FILE ./toolchain.cmake) # toolchain is detected correctly
set(ISYSTEM_PATH somePath)
add_compile_options(-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard) # compile option for all targets, which is correctly passed to the compiler
include_directories(SYSTEM ${ISYSTEM_PATH}) # include path for all targets, which is not passed to the compiler

project(someProject LANGUAGES C)
add_subdirectory(shared)
# other subdirectories
# one of the subdirectory
project(shared LANGUAGES C)
add_library(${PROJECT_NAME} STATIC
    shared.c
)
# display target includes
get_target_property(sharedIncludes ${PROJECT_NAME} INCLUDE_DIRECTORIES)
message("shared target includes")
message("[")
foreach(dir ${dirIncludes})
    message(STATUS "${dir}")
endforeach()
message("]")

The message shows the shared target includes has somePath from the top CMakeLists. But the include path is not passed to the compiler. Where does it go wrong? Thanks.

CMake version 3.27.4. The compiler is arm-none-eabi-gcc.

What is the real value you’re setting ISYSTEM_PATH to? Would that path possibly be one of the default paths the compiler already searches? If so, I think CMake will remove it from the command line, since it is already searched by the compiler by default.

ISYSTEM_PATH is the compiler’s default paths indeed. I add that so that the path will be in the exported compile_commands.json, so that clang based tools (clangd) can see the system path.

Tools that read compile_commands.json have to understand the tool used in the command line there (this will only get worse with C++ modules as CMake will only generate modules for the actual compiler and clang-tidy, clangd, etc. aren’t likely to learn GCC’s module format anytime soon to do the import when doing its thing). I’d recommend using a Clang build of the project for such use cases. Or teach Clang how to understand the compiler being used more natively (e.g., how it does so when given a GCC command line). Cross-compiles seem to need more work here.

Thanks for the replies. The workaround I get is add -isystem as compiler flags in add_compile_options.

# top CMakeLists
set(ISYSTEM_PATH somePath)
list(TRANSFORM ISYSTEM_PATH REPLACE ".+" "SHELL:-isystem \\0" OUTPUT_VARIABLE ISYSTEM_FLAGS)
# ISYSTEM_FLAGS should be "SHELL:-isystem path1";"SHELL:-isystem path2"

add_compile_options(${ISYSTEM_FLAGS}) # replace include_directories(SYSTEM ${ISYSTEM_PATH})