如何让CMake基于GCC版本传递std = c ++ 14/c ++ 1y或c ++ 17/c ++ 1z?

ein*_*ica 41 c++ cmake gcc4 c++14

GCC 4.x不接受--std=c++14C++ 14代码的切换 - 它需要--std=c++1y代替.以后的版本需要(--std=c++1z但可能)--std=c++17还没有设置(2016年写这个).也许C++ 11也存在类似的问题.

CMake是否有一些设施(可能作为模块)根据GCC版本传递正确的开关?

Cra*_*ott 70

当想要指定一个特定的C++版本,推荐的方法通过CMake 3.1做到这一点,后面是使用CXX_STANDARD,CXX_STANDARD_REQUIRED并且CXX_EXTENSIONS目标属性,或者它们的等同物变量来指定目标的默认值.完整的细节可以在这里找到,但简短的版本是这样的:

cmake_minimum_required(VERSION 3.1)
project(Example)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# ... Define targets, etc. as usual
Run Code Online (Sandbox Code Playgroud)

然后,CMake应根据编译器支持的内容为所请求的C++标准选择适当的编译器标志,否则如果它不支持所请求的标准则输出错误.

还应注意,CMake可以将目标升级为使用比其CXX_STANDARD目标属性指定的语言标准更晚的语言标准.使用编译功能要求(如@FlorianWolters答案中所述)可以提高语言标准要求.事实上,CMake将始终选择CXX_STANDARD目标属性或目标上设置的编译功能要求所指定的更强大的语言要求.另请注意,3.10.1中的CMake文档并未准确反映CXX_EXTENSIONS与编译功能交互的方式,因为CXX_EXTENSIONS只有在CXX_STANDARD大多数常见编译器中都指定时才会生效(因为它们与一个编译器标志一起指定).

  • 我建议设置所有三个。CMAKE_CXX_STANDARD 本身并不能保证您获得 C++ 标准。在未将 CMAKE_CXX_STANDARD_REQUIRED 设置为 true 的情况下,如果 CMAKE_CXX_STANDARD 请求的版本不可用,则允许 CMake 回退到较旧的 C++ 版本。将 CMAKE_CXX_EXTENSIONS 设置为 false 可确保您的项目不使用非标准 C++,但同样重要的是,它可能会影响您的二进制文件链接到的标准库。政策 CMP0128 也相关。 (3认同)

Flo*_*ers 23

现代CMake代码应该使用该target_compile_features命令来请求特定的C++标准.这可以指定为仅构建要求(PRIVATE),仅使用要求(INTERFACE)或构建和使用要求(PUBLIC).

例:

cmake_minimum_required(VERSION 3.9.4)

project(cpp-snippets)
add_executable(cpp-snippets "main.cpp")
target_compile_features(cpp-snippets PRIVATE cxx_std_17)
Run Code Online (Sandbox Code Playgroud)

有关cmake-compile-features的官方CMake文档,请参阅" 需要语言标准 "一节以了解更多信息.

  • 还应该强调的是,对cxx_std_YY`元功能的支持也仅在CMake 3.8中添加,而目标属性的`CXX_STANDARD`系列已经存在更长时间并且单独的`cxx_std_YY`元功能无法控制可以使用编译器扩展. (5认同)
  • 与“使用要求”相对的“构建要求”是什么? (2认同)
  • @einpoklum 如答案中所用,_build requirements_ 指的是构建目标本身所需的东西,而 _usage requirements_ 是任何与目标链接的东西都将作为要求继承的东西。 (2认同)

Som*_*ude 10

检查编译器是否支持标志?也许是这样的

include(CheckCXXCompilerFlag)

# Check for standard to use
check_cxx_compiler_flag(-std=c++17 HAVE_FLAG_STD_CXX17)
if(HAVE_FLAG_STD_CXX17)
    # Have -std=c++17, use it
else()
    check_cxx_compiler_flag(-std=c++1z HAVE_FLAG_STD_CXX1Z)
    if(HAVE_FLAG_STD_CXX1Z)
        # Have -std=c++1z, use it
    else()
        # And so on and on...
    endif()
endif()
Run Code Online (Sandbox Code Playgroud)

  • @einpoklum没有猜测,我已经使用这个确切的代码几年没有问题.有了GCC和Clang(我上次试过的时候不支持`-std = c ++ 17`选项). (2认同)