
Compile bug: GCC 16.1 error
快速结论:该报错发生在使用 GCC 16.x 编译 llama.cpp 并启用 CUDA 后端时。CUDA 工具链对宿主 GCC 版本有严格限制,GCC 16 当前不受支持,优先排查降级 GCC 版本,替代方案是设置 CMAKE_CUDA_HOST_COMPILER 指向受支持的 GCC(如 GCC 14)。
问题场景
用户尝试在 Arch Linux 系统上编译 llama.cpp(Git commit 未指定),使用 cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release 进行编译配置。系统安装了 CUDA 13(具体版本为 13.2.78)和 GCC 16.1.1。CMake 在检测 CUDA 编译器时失败,错误来自 type_traits 头文件中的 char8_t 未定义。
报错原文
/usr/include/c++/16.1.1/type_traits(393): error: identifier "char8_t" is
undefined
struct __is_integral_helper
^
/usr/include/c++/16.1.1/type_traits(1448): error: identifier "__f" is
undefined
= requires (void(&__f)(_Tp)) { __f({}); };
^
...
CMake Error at /usr/share/cmake/Modules/CMakeDetermineCompilerId.cmake:934 (message):
Compiling the CUDA compiler identification source file
"CMakeCUDACompilerId.cu" failed.
原因分析
可能原因是 CUDA 的宿主编译器(host compiler)不支持 GCC 16。Issue 评论指出 CUDA 有宿主编译器支持策略(Host Compiler Support Policy),需参考兼容性矩阵:https://docs.nvidia.com/cuda/cuda-installation-guide-linux/#host-compiler-support-policy。NVCC 在预处理阶段调用宿主 GCC 时,--gnu_version=160101 表示检测到 GCC 16.1.1,但 CUDA 13.x 工具链的标准库头文件与此版本不兼容,导致 char8_t 等 C++20 特性解析失败。
环境排查
- GCC 版本:确认系统中
gcc --version是否为 16.x。示例日志中显示系统同时安装了 GCC 14.3.1 和 GCC 16.1.1。 - CUDA 版本:确认 CUDA Toolkit 版本,示例为 CUDA 13.2.78。
- CMake 版本:确认
cmake --version,但非必要,因为根因不在 CMake。 - 操作系统:Arch Linux,但问题与发行版无关。
解决步骤
- 降级默认 GCC 版本:使用
sudo pacman -S gcc14安装 GCC 14,并通过gcc --version && g++ --version确认系统默认版本已切换至 14.x。如果系统已有多个 GCC,可通过update-alternatives或设置环境变量CC=/usr/bin/gcc-14 CXX=/usr/bin/g++-14指定编译器。 - 设置 CUDA 宿主编译器:在 CMake 命令中指定 CUDA 宿主编译器为受支持的 GCC,例如:
cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_HOST_COMPILER=/usr/bin/g++-14 - 重试编译:先清理
build目录(rm -rf build),再执行上一步的 CMake 配置命令。 - 确认 CUDA 版本支持的 GCC 范围:查阅 NVIDIA 官方支持矩阵,确保宿主 GCC 版本在列表之内。例如 CUDA 13.x 通常支持 GCC 12、13、14 但不支持 16。
验证方法
执行完整的 CMake 配置命令后,观察输出应不再出现 CMake Error at ... CMakeDetermineCompilerId.cmake:934 错误,并且 -- Compiling the CUDA compiler identification source file ... succeeded 表示 CUDA 编译器识别成功。然后执行 cmake --build build --config Release -j $(nproc),应顺利编译完成。



