Clangd 无法识别 CMake 生成的 CUDA --options-file 标识

tl.dr

CMake 生成的 compile_commands.json 中,对 .cu 文件会生成 –options-file 的标识,而 clangd 无法识别,从而导致 clangd 报错无法找到头文件。

解决:在 CMake 中关闭为 cuda 生成 –options-file 的选项

# This would work
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
# You can add below if you like
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)

或者用其他能正确生成 compile_commands.json 的工具。比如 bear 或者 xmake。

原因

使用 CMake(3.25.2) 构建工程,某些 .cu 文件里需要 include header目录下的头文件。

include_directories(header)

生成的 nvcc 编译命令理应长这样:

nvcc *.cu -I/.../header ...

但是,CMake 实际生成了:

nvcc *.cu --options-file .../includes_CUDA.rsp

找到 includes_CUDA.rsp,里面存放了 -I 的 flags。

-I/.../header

而这个 --options-file 选项是 nvcc 独有的,并且 clangd(18.1.3) 似乎无法识别。导致 .cu 在 IDE 中无法识别头文件。

这个选项是为了防止 include 和 link 的目录太多,导致命令过长而诞生的 大名为 response file How to force CMake to use a response file when linking CUDA on Windows? - Stack Overflow

解决

搜索了一会没找到从 Clangd 入手的解决方法。只能从 CMake 入手。关闭 --options-file 的选项即可,CMake 会生成正常的 -I 选项。

其他

除了 --options-file,CMake 还会生成一些 Clangd 无法识别的标识,比如:

  • -forward-unknown-to-host-compiler
  • –generate-code
  • 待发现

稍好的解决方法是在 compile_commands.json 同目录下写一个 .clangd 配置,把这些 clangd 无法识别的标识替换掉。

CompileFlags:
  Add:
    - --cuda-path=/usr/local/cuda
    - --cuda-gpu-arch=sm_89
    - -L/usr/local/cuda/lib64
    - -I/usr/local/cuda/include
  Remove:
    - -forward-unknown-to-host-compiler
    - --generate-code*
    - --options-file

参考

https://github.com/clangd/vscode-clangd/issues/592#issuecomment-2036788981