You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake自动添加的/Zc:__cplusplus被nvcc误判为文件名求助

问题:CMake传递/Zc:__cplusplus参数给nvcc时解析错误

我在Windows环境下开发C++项目,使用CUDA 12.0、CMake 3.31.6及vcpkg(已更新至提交a62ce77)。CMake配置阶段调用nvcc获取编译器信息时,执行命令如下:

"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.0\bin\nvcc.exe" -D_WINDOWS "-Xcompiler= /GR /EHsc" --std=c++17 --expt-relaxed-constexpr --expt-extended-lambda -Xcudafe --display_error_number,--diag_suppress=[186,611,1388,1394,2809,20011,20012,20014,20054] -Xptxas -dlcm=ca --resource-usage -Xcompiler=/arch:AVX2 "-Xcompiler= -Zi -Ob0 -Od /RTC1" -std=c++17 -arch=native -Xcompiler=-MDd -D_ITERATOR_DEBUG_LEVEL=0 /Zc:__cplusplus --dryrun -forward-unknown-to-host-compiler C:\Users\Me\AppData\Local\Temp\compiler-file17533896127583160454.cu

nvcc返回错误:

nvcc fatal   : Don't know what to do with 'F:/Zc:__cplusplus'

/Zc:__cplusplus参数需要添加-Xcompiler前缀才能被nvcc识别为宿主编译器选项,但现在被当作文件名处理。我没有手动在CMakeLists.txt中指定该参数,推测是CMake自动添加,但找不到对应的变量。

通过最小复现案例发现问题与spdlog::spdlog_header_only相关,移除该依赖或替换为spdlog::spdlog可解决,但我需要使用header-only版本。

最小复现配置

CMakeLists.txt

cmake_minimum_required (VERSION 3.18)
project(Foo LANGUAGES CXX CUDA)
set(CMAKE_CXX_STANDARD 20)
find_package(spdlog CONFIG REQUIRED)
add_library(Foo
        STATIC
        empty.cu
)
target_link_libraries(Foo
        PUBLIC
        spdlog::spdlog_header_only
)

vcpkg.json

{
  "name": "foo",
  "version-string": "0.0.1",
  "dependencies": [
    "spdlog"
  ]
}

vcpkg-configuration.json

{
  "default-registry": {
    "kind": "git",
    "repository": "https://github.com/Microsoft/vcpkg",
    "baseline": "a62ce77d56ee07513b4b67de1ec2daeaebfae51a"
  }
}

CMake调用命令

"C:\Program Files\CMake\bin\cmake.exe" -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_MAKE_PROGRAM=C:/Program Files/JetBrains/CLion 2024.3.4/bin/ninja/win/x64/ninja.exe" -G Ninja -DCMAKE_TOOLCHAIN_FILE=F:\Libraries\vcpkg\scripts\buildsystems\vcpkg.cmake -S F:\Projects\MyProject -B F:\Projects\MyProject\cmake-build-debug

配置输出报错片段

-- Running vcpkg install
...
All requested installations completed successfully in: 224 us
-- Running vcpkg install - done
-- Configuring done (1.4s)
-- Generating done (0.0s)
-- Build files have been written to: F:/Projects/MyProject/cmake-build-debug

Cannot get compiler information:
    Compiler exited with error code 1: "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.0\bin\nvcc.exe" -DFMT_SHARED -DSPDLOG_FMT_EXTERNAL -DSPDLOG_FWRITE_UNLOCKED -isystem=F:/Projects/MyProject/cmake-build-debug/vcpkg_installed/x64-windows/include -D_WINDOWS "-Xcompiler= /GR /EHsc" "-Xcompiler= -Zi -Ob0 -Od /RTC1" -std=c++20 --generate-code=arch=compute_52,code=[compute_52,sm_52] -Xcompiler=-MDd /Zc:__cplusplus --dryrun -forward-unknown-to-host-compiler C:\Users\me\AppData\Local\Temp\compiler-file17655800990905755916.cu

解决方法

1. 修正spdlog_header_only的INTERFACE编译选项

由于spdlog::spdlog_header_only是INTERFACE目标,会将MSVC的CXX编译选项传递给依赖它的CUDA目标,但CMake不会自动为CUDA目标转换这些选项。可以手动修改该目标的选项,将/Zc:__cplusplus包装成nvcc可识别的形式:

find_package(spdlog CONFIG REQUIRED)
# 遍历spdlog_header_only的INTERFACE_COMPILE_OPTIONS,修正/Zc:__cplusplus
get_target_property(_spdlog_interface_opts spdlog::spdlog_header_only INTERFACE_COMPILE_OPTIONS)
list(TRANSFORM _spdlog_interface_opts REPLACE "^/Zc:__cplusplus$" "$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:__cplusplus>$<$<NOT:$<COMPILE_LANGUAGE:CUDA>>:/Zc:__cplusplus>")
set_target_properties(spdlog::spdlog_header_only PROPERTIES INTERFACE_COMPILE_OPTIONS "${_spdlog_interface_opts}")

2. 全局设置CUDA的编译选项

如果希望全局生效,可以直接将/Zc:__cplusplus添加到CMAKE_CUDA_FLAGS中,自动带上-Xcompiler前缀:

set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=/Zc:__cplusplus")

注意:如果项目中同时有CXX和CUDA目标,CXX目标的/Zc:__cplusplus会由CMake自动处理,无需重复添加。

3. 针对单个CUDA目标修正选项

只针对出现问题的CUDA目标调整编译选项,移除错误的/Zc:__cplusplus并添加正确的带前缀版本:

add_library(Foo STATIC empty.cu)
# 移除目标上的/Zc:__cplusplus选项
get_target_property(_foo_compile_opts Foo COMPILE_OPTIONS)
list(REMOVE_ITEM _foo_compile_opts "/Zc:__cplusplus")
set_target_properties(Foo PROPERTIES COMPILE_OPTIONS "${_foo_compile_opts}")
# 添加正确的nvcc格式选项
target_compile_options(Foo PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:__cplusplus>)

CMake中/Zc:__cplusplus的控制逻辑

  1. 自动添加触发条件:当CMake检测到使用MSVC编译器,且设置了CMAKE_CXX_STANDARD(如20)并开启CMAKE_CXX_STANDARD_REQUIRED(默认开启)时,会自动添加/Zc:__cplusplus到CMAKE_CXX_FLAGS中,目的是让MSVC正确报告C++标准版本。

  2. INTERFACE目标的传递问题:spdlog::spdlog_header_only作为INTERFACE目标,会将自身的INTERFACE_COMPILE_OPTIONS(包括从CMAKE_CXX_FLAGS继承的/Zc:__cplusplus)传递给所有依赖它的目标,包括CUDA语言目标。

  3. CUDA语言的处理缺陷:CMake在处理CUDA目标时,会自动将CMAKE_CXX_FLAGS中的部分选项转换为-Xcompiler前缀形式,但对于通过INTERFACE目标传递的选项,可能没有正确处理,导致/Zc:__cplusplus直接被传递给nvcc,而非包装成宿主编译器选项。

内容的提问来源于stack exchange,提问作者CygnusX1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:14:54