CMake target_include_directories doesn't export to compile_commands.json when using CUDA

I am trying to use CMake to build a CUDA project. However, when I use add_library followed by target_include_directories, the relevant commands are not updated in the compile_commands.json file.
Screenshot 2024-02-12 at 21.45.05
The structure of the project is shown here. There are three CMakeLists.txt; one in Euler_CUDA, one in src and one in solver. In sequence, the CMakeLists are the following:

cmake_minimum_required(VERSION 3.19)

project(CUDA_Practice)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Werror -pedantic")
enable_language(CUDA)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)

add_subdirectory(src)

execute_process(
    COMMAND ${CMAKE_COMMAND} -E create_symlink
        ${CMAKE_BINARY_DIR}/compile_commands.json
        ${CMAKE_SOURCE_DIR}/compile_commands.json
)
add_subdirectory(solver)

find_package(PkgConfig REQUIRED)
pkg_search_module(LIBCONFIG++ REQUIRED libconfig++)

add_executable(main main.cu)
target_include_directories(main PUBLIC ${LIBCONGIG++_INCLUDE_DIRS})

target_link_libraries(main PUBLIC solver_lib)
target_link_libraries(main PUBLIC ${LIBCONFIG++_LINK_LIBRARES})
add_library(solver_lib STATIC solver.cu equationOfState.cu)

target_include_directories(solver_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

And the compile_commands.json file which is output looks like the following

[
{
  "directory": "/home/raid/sy451/Euler_CUDA/build/src",
  "command": "/lsc/opt/cuda-11.7/bin/nvcc -forward-unknown-to-host-compiler  --options-file CMakeFiles/main.dir/includes_CUDA.rsp -std=c++17 \"--generate-code=arch=compute_52,code=[compute_52,sm_52]\" -x cu -c /home/raid/sy451/Euler_CUDA/src/main.cu -o CMakeFiles/main.dir/main.cu.o",
  "file": "/home/raid/sy451/Euler_CUDA/src/main.cu",
  "output": "src/CMakeFiles/main.dir/main.cu.o"
},
{
  "directory": "/home/raid/sy451/Euler_CUDA/build/src/solver",
  "command": "/lsc/opt/cuda-11.7/bin/nvcc -forward-unknown-to-host-compiler  --options-file CMakeFiles/solver_lib.dir/includes_CUDA.rsp -std=c++17 \"--generate-code=arch=compute_52,code=[compute_52,sm_52]\" -x cu -c /home/raid/sy451/Euler_CUDA/src/solver/solver.cu -o CMakeFiles/solver_lib.dir/solver.cu.o",
  "file": "/home/raid/sy451/Euler_CUDA/src/solver/solver.cu",
  "output": "src/solver/CMakeFiles/solver_lib.dir/solver.cu.o"
},
{
  "directory": "/home/raid/sy451/Euler_CUDA/build/src/solver",
  "command": "/lsc/opt/cuda-11.7/bin/nvcc -forward-unknown-to-host-compiler  --options-file CMakeFiles/solver_lib.dir/includes_CUDA.rsp -std=c++17 \"--generate-code=arch=compute_52,code=[compute_52,sm_52]\" -x cu -c /home/raid/sy451/Euler_CUDA/src/solver/equationOfState.cu -o CMakeFiles/solver_lib.dir/equationOfState.cu.o",
  "file": "/home/raid/sy451/Euler_CUDA/src/solver/equationOfState.cu",
  "output": "src/solver/CMakeFiles/solver_lib.dir/equationOfState.cu.o"
}
]

As you can see, there is no -I flag with the include directory mentioned anywhere. However, when I create an analogous C++ project, it works fine, leading me to believe that the problem is with CMake and CUDA. The project compiles fine but it poses a problem when I use clangd. My temporary solution is to manually add the include flags to the compile_commands.json but it would be nice if the flag could be explicitly output.

Did you perhaps mean LIBCONFIG++_INCLUDE_DIRS here?

I’m getting the same behaviour. Any -I flag is not being forwarded to the compiler flags for nvcc, but is for regular C++ compilation. I do see that for nvcc, the compile_commands.json has a --options-file CMakelists/<>.rsp entry, whose file does have the include flags, but LSPs like clangd can’t read that.

I guess my question is, why are the include flags being placed into the *.rsp file instead of directly into the compile_commands.json for the cuda targets, but not regular C++ targets?

Yes, that’s what I meant!

Yeah I believe that is the case. One solution is to add these extra flags to the .clangd file.

From this issue here, it appears that there was a regression with clangd and reading the response files: clangd 17 regression: response files are not expanded when using command inference · Issue #69690 · llvm/llvm-project · GitHub

It appears that there was a way to not use the response files and have the include flags directly into the compile command by using -DCMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES=OFF, but I have not had success with that.

Based on what I read, it seems that this problem is likely to be fixed in clangd 18.

any update on this?

I’m having the same issue and I’m using clangd 18.1.3.

What worked for me is adding the following to my cmakelists

set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
1 Like

try to edit /usr/share/cmake/Modules/Compiler/NVIDIA.cmake, delete --option-files and RESPONSE_FILE content at the end of the file. it works for me