PAYATHON 2026

系统更新后,CLion 配置失败并提示无法获取编译器信息,如何解决?

排障赵师傅

日志显示,当前失败的直接原因是宏定义参数有误:一个 CUDA 头文件目录被放在了 -D 后面,另一个宏定义的双引号没有闭合。先修正生成这些参数的配置,再重新加载 CLion 的 CMake 配置。

系统升级可能改变了编译器、依赖包或 CMake 变量的取值,但现有日志还不足以判断这是 Devuan、GCC 15 或 CUDA 13.1 的兼容性问题。

日志中哪些内容说明了原因?

导致退出的报错是:

<command-line>: error: macro names must be identifiers
<command-line>: warning: missing terminating " character

对应的异常参数是:

-D/usr/local/cuda/targets/x86_64-linux/include/cccl\"
-DCUDA_INCLUDE_DIR=\"/usr/local/cuda/targets/x86_64-linux/include

-D 用于定义预处理宏,通常写成:

-DMACRO_NAME
-DMACRO_NAME=value

第一项把 /usr/local/cuda/.../cccl" 当成了宏名。路径中包含 / 等字符,不符合宏标识符的要求,因此报错。

第二项似乎是要定义一个字符串宏,但编译器收到的值只有开头的 ",缺少结尾的 "。COLLECT_GCC_OPTIONS 中也记录了这两个异常参数,说明编译器实际收到的参数确实有问题。

日志中还有这些信息:

ignoring duplicate directory ...
ignoring nonexistent directory ...

这是 GCC 在详细输出模式下报告的搜索目录处理情况,既不能据此判断编译器安装损坏,也无法用它解释当前的宏名错误。

为什么复制到终端执行,看起来没有报错?

两次调用并不完全相同。CLion 的日志显示,编译器预处理了一个临时文件:

/tmp/compiler-file2738036496762326047

手动执行的命令没有显式提供输入文件,也没有用 - 指定从标准输入读取。因此,只看到 GCC 的版本和配置信息,还不能证明执行了相同的预处理过程。

可以先运行不带项目参数的命令:

/usr/bin/c++ -x c++ -E -v -dD - </dev/null >/dev/null
echo $?

再加入日志中有问题的宏定义:

/usr/bin/c++ -x c++ -E -v -dD \
  '-D/usr/local/cuda/targets/x86_64-linux/include/cccl"' \
  '-DCUDA_INCLUDE_DIR="/usr/local/cuda/targets/x86_64-linux/include' \
  - </dev/null >/dev/null
echo $?

这两条命令都明确提供了空输入;第二条还用 shell 单引号保留了参数中的双引号。第一条检查基础预处理调用,第二条验证异常参数,执行后要同时查看标准错误输出和退出码。

这组命令只检查预处理阶段,项目能否完整编译、链接,还需要另行验证。

如何找到错误参数的来源?

先在项目的 CMakeLists.txt 和 .cmake 文件中搜索:

CUDA_INCLUDE_DIR
CUDA_INCLUDE_DIRS
cccl
target_compile_definitions
add_compile_definitions
add_definitions
CMAKE_CXX_FLAGS

还要检查 CLion 的 CMake Profile、CMakePresets.json、工具链文件,以及环境变量 CXXFLAGS、CPPFLAGS。Debug 和 Release 都失败,可以优先检查它们共用的配置。

留意是否有类似写法:

# 如果变量中包含多个目录,这种写法容易产生错误参数。
target_compile_definitions(app PRIVATE
    CUDA_INCLUDE_DIR="${CUDA_INCLUDE_DIRS}"
)

CMake 用分号表示列表。假设变量展开后是:

/usr/local/cuda/targets/x86_64-linux/include;/usr/local/cuda/targets/x86_64-linux/include/cccl

将整个列表放进一个字符串宏,可能在后续展开、转义时拆成两个定义,出现日志中字符串引号不完整、目录被当成宏名的情况。

这个排查方向与日志吻合,但具体是哪处配置造成的,还需要检查项目。可以临时打印相关变量:

message(STATUS "CUDA_INCLUDE_DIR=[${CUDA_INCLUDE_DIR}]")
message(STATUS "CUDA_INCLUDE_DIRS=[${CUDA_INCLUDE_DIRS}]")

如果项目使用了其他变量名,就打印实际传入宏定义的变量。同时检查依赖目标是否通过 INTERFACE_COMPILE_DEFINITIONS 传播了错误参数。

如何正确修改 CMake 配置?

头文件目录使用 target_include_directories()

如果这些路径用于查找 CUDA 头文件,应将它们作为包含目录传入:

# app 替换为项目中已有的目标名称。
target_include_directories(app SYSTEM PRIVATE
    "/usr/local/cuda/targets/x86_64-linux/include"
    "/usr/local/cuda/targets/x86_64-linux/include/cccl"
)

路径按实际安装位置调整。如果项目已经通过依赖包提供的目标或变量获取包含目录,优先沿用已有配置,避免重复硬编码。

还需要删除原来把这些目录传给宏定义的代码。只补上包含目录,错误的 -D 参数仍会导致失败。日志中已经有相应的 -isystem 参数,应检查同一组目录是否同时被传给了包含路径和宏定义。

确实需要字符串宏时,只传入单个值

如果 C++ 代码确实会读取 CUDA_INCLUDE_DIR,就为它指定一个明确的目录,不要传入目录列表:

set(project_cuda_include_dir
    "/usr/local/cuda/targets/x86_64-linux/include"
)

target_compile_definitions(app PRIVATE
    "CUDA_INCLUDE_DIR=\"${project_cuda_include_dir}\""
)

预期生成的宏相当于:

#define CUDA_INCLUDE_DIR "/usr/local/cuda/targets/x86_64-linux/include"

如果代码没有使用这个宏,直接删除该定义即可。修改时保留 SPDLOG_COMPILED_LIB 等无关且合法的宏。

修改后如何让 CLion 重新配置?

保存 CMake 修改,重新加载项目,并分别检查 Debug、Release 的结果。如果日志里仍有旧参数,可以重置 CLion 的 CMake 缓存并重新加载,具体菜单名称以所用版本为准。

也可以为对应 Profile 换一个新的构建目录,排除旧缓存的影响。不要直接删除源码目录,也不必一开始就清除整个 IDE 的所有缓存。

验证时应确认:

  • 新日志中不再出现 -D/usr/local/cuda/...。
  • 如果仍有 CUDA_INCLUDE_DIR,它的字符串引号完整。
  • 编译器信息提取、CMake 配置和实际构建都能完成。

Cannot get compiler information 表示 CLion 获取编译器信息失败。仅凭这条消息,还不能判断 CMake 自身的编译器检测也失败了。如果修复参数后仍有问题,应查看完整的 CMake 输出,确认失败发生在哪个阶段。

仍然失败时,需要补充哪些信息?

继续排查时,需要提供:

  • CLion、CMake 的版本,以及当前 Profile 使用的工具链和编译器路径。
  • 设置 CUDA 包含目录、宏定义的 CMake 代码,以及相关变量展开后的值。
  • 修复后的首个错误的完整信息和实际编译命令;如果已经生成 compile_commands.json,也可以提供其中的相关条目。
  • 如果项目编译 .cu 文件,还需提供 nvcc --version 和所选主机编译器。

系统升级后,也要核对 CLion 实际使用的编译器是否发生了变化。如果随后出现 nvcc 不支持主机编译器的明确报错,再按 CUDA 13.1 的支持要求处理。当前日志表明应先修正错误的 -D 参数,还没有依据认定必须降级 GCC 或重装 CUDA。

备注:内容仅供参考。