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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42834844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 15:31:45  来源:igfitidea点击:

How to get CMake to pass either std=c++14/c++1y or c++17/c++1z based on GCC version?

c++cmakec++14gcc4

提问by einpoklum

GCC 4.x doesn't accept the --std=c++14switch for C++14 code - it takes --std=c++1yinstead. Later versions take --std=c++1zbut (probably) not --std=c++17which has not been set yet (writing this in 2016). Perhaps there are similar issues with C++11.

GCC 4.x 不接受--std=c++14C++14 代码的开关 ---std=c++1y取而代之。后来的版本采用--std=c++1z但(可能)--std=c++17尚未设置(在 2016 年编写)。也许 C++11 也有类似的问题。

Does CMake have some facility (perhaps as a module) to pass the correct switch according to the GCC version?

CMake 是否有一些工具(也许作为一个模块)来根据 GCC 版本传递正确的开关?

回答by Craig Scott

When wanting to specify a particular C++ version, the recommended way to do this with CMake 3.1 and later is to use the CXX_STANDARD, CXX_STANDARD_REQUIREDand CXX_EXTENSIONStarget properties, or their variable equivalents to specify target defaults. Full details can be found here, but the short version goes something like this:

当想要指定特定的 C++ 版本时,推荐使用 CMake 3.1 及更高版本执行此操作的方法是使用CXX_STANDARD,CXX_STANDARD_REQUIREDCXX_EXTENSIONStarget 属性,或它们的变量等效项来指定目标默认值。完整的细节可以在这里找到,但简短的版本是这样的:

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

CMake should then select the appropriate compiler flag for the requested C++ standard based on what the compiler supports, or error out if it doesn't support the requested standard.

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

It should also be noted that CMake may upgrade the target to use a later language standard than the one specified by its CXX_STANDARDtarget property. The use of compile feature requirements(as mentioned in @FlorianWolters answer) can raise the language standard requirement. In fact, CMake will always pick the stronger language requirement specified by either the CXX_STANDARDtarget property or the compile feature requirements set on the target. Note also that the CMake documentation as of 3.10.1 does not accurately reflect the way CXX_EXTENSIONSinteracts with compile features, as CXX_EXTENSIONSonly takes effect if CXX_STANDARDis also specified for most common compilers (since they are specified together with the one compiler flag).

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

回答by Florian Wolters

Modern CMake code should use the target_compile_featurescommand to request a specific C++ standard. This can be specified as build requirement only (PRIVATE), usage requirement only (INTERFACE) or build and usage requirement (PUBLIC).

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

Example:

例子:

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)

Refer to the section Requiring Language Standardsin the official CMake documentation for cmake-compile-featuresto learn more.

有关cmake-compile-features 的更多信息,请参阅官方 CMake 文档中的“要求语言标准”部分。

回答by Some programmer dude

Check if the compiler supports the flags? Perhaps something like

检查编译器是否支持这些标志?也许像

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()