为什么CMake在使用MSVC编译时会引入 -std:c++14,而不是 /std:c++14?

后端开发 2026-07-09

我正在尝试构建我的一个程序,使用CMake进行构建配置(通过CLion进行工作)。这个程序的目标需要C++14,因此我定义了:

foreach(tgt ${compiled-targets})
    set_target_properties(
    ${tgt}
    PROPERTIES
    CXX_STANDARD 14
    CXX_STANDARD_REQUIRED YES
        CXX_EXTENSIONS NO
    )
    # etc. etc.
endforeach(tgt)

不幸的是,实际编译时,命令行是:

C:\PROGRA~1\MICROS~4\18\COMMUN~1\VC\Tools\MSVC\1450~1.357\bin\Hostx64\x64\cl.exe
/nologo /TP -DSPDLOG_COMPILED_LIB -IC:\Users\250026754\src\gpu-kernel-runner\src
-external:IC:\Users\250026754\src\gpu-kernel-runner\third-party 
-external:IC:\Users\250026754\installed\include 
-external:IC:\Users\250026754\installed\cuda-api-wrappers\include 
-external:I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.2\include" 
-external:I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.2\include\cccl" 
-external:W0 /DWIN32 /D_WINDOWS /GR /EHsc /O2 /Ob2 /DNDEBUG -std:c++14 
-MD /W4 /showIncludes /FoCMakeFiles\kernel-runner.dir\src\nvrtc-related\build.cpp.obj /FdCMakeFiles\kernel-runner.dir\ 
/FS -c C:\Users\250026754\src\gpu-kernel-runner\src\nvrtc-related\build.cpp

你会注意到用于指定标准的开关是 -std:c++14,而不是 /std:c++14,这是MSVC编译器 expects。我还注意到有些其他选项使用连字符而不是斜杠。

为什么会这样?以及 - 如何让CMake/Ninja发出适当的开关起始字符?

PS - 我使用CLion 2026.1.1,随附的CMake(我记得是4.2.2)以及CUDA 13.2

解决方案

tl;dr:CMake的行为没问题;也再加上 -Zc:__cplusplus

你的问题不是出在CMake;它生成的是一个合法的标志。你要知道,MSVC编译器(cl.exe)接受通过 任意一种 方式指定的开关,即通过连字符(-)或斜杠(/)所指定的开关。因此你的编译器确实在尝试用C++14标准来编译你的程序……只是它的支持有点不稳定。具体来说,MSVC不定义 __cplusplus 这个预处理宏,你的代码可能会尝试检查它的值并报错,例如:

static_assert(__cplusplus >= 201402L, "C++2014 is required to compile this program");

要解决这个问题,你需要再传递一个命令行选项:/Zc:__cplusplus(或可选地,-Zc:__cplusplus)。这将正确地让定义成立。

编辑: 你也可能想使用 /Zc:preprocessor,让(较新的)MSVC预处理器更好地符合C 与C++的语言标准。请参阅 此描述

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章