如何让 CMake 根据 GCC 版本通过 std=c++14/c++1y 或 c++17/c++1z?
How to get CMake to pass either std=c++14/c++1y or c++17/c++1z based on GCC version?
GCC 4.x 不接受 C++14 代码的 --std=c++14
开关 - 它需要 --std=c++1y
代替。更高版本采用 --std=c++1z
但(可能)不是 --std=c++17
尚未设置(在 2016 年编写)。也许 C++11 也有类似的问题。
CMake 是否有一些工具(可能作为一个模块)根据 GCC 版本传递正确的开关?
检查编译器是否支持标志?也许像
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()
当想要指定特定的 C++ 版本时,使用 CMake 3.1 及更高版本执行此操作的推荐方法是使用 CXX_STANDARD
、CXX_STANDARD_REQUIRED
和 CXX_EXTENSIONS
目标属性,或者它们的变量等价物来指定目标默认值。可以找到完整的详细信息 here,但简短的版本是这样的:
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 然后应该 select 根据编译器支持的内容为请求的 C++ 标准设置适当的编译器标志,或者如果它不支持请求的标准则出错。
还应注意,CMake 可能会升级目标以使用比其 CXX_STANDARD
目标 属性 指定的语言标准更新的语言标准。使用 compile feature requirements (如@FlorianWolters 回答中所述)可以提高语言标准要求。事实上,CMake 将始终选择由 CXX_STANDARD
目标 属性 或目标上设置的编译功能要求指定的更强的语言要求。另请注意,早期版本的 CMake 文档并未准确反映 CXX_EXTENSIONS
与编译功能交互的方式。对于 CMake 3.21 或更早版本,CXX_EXTENSIONS
仅在还指定了 CXX_STANDARD
时才会生效,对于大多数常见的编译器(因为它们与一个编译器标志一起指定)。从 CMake 3.22 开始,无论 CXX_STANDARD
是否设置,CXX_EXTENSIONS
都被尊重。
现代 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)
请参阅 cmake-compile-features 的官方 CMake 文档中的 需要语言标准 部分以了解更多信息。
GCC 4.x 不接受 C++14 代码的 --std=c++14
开关 - 它需要 --std=c++1y
代替。更高版本采用 --std=c++1z
但(可能)不是 --std=c++17
尚未设置(在 2016 年编写)。也许 C++11 也有类似的问题。
CMake 是否有一些工具(可能作为一个模块)根据 GCC 版本传递正确的开关?
检查编译器是否支持标志?也许像
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()
当想要指定特定的 C++ 版本时,使用 CMake 3.1 及更高版本执行此操作的推荐方法是使用 CXX_STANDARD
、CXX_STANDARD_REQUIRED
和 CXX_EXTENSIONS
目标属性,或者它们的变量等价物来指定目标默认值。可以找到完整的详细信息 here,但简短的版本是这样的:
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 然后应该 select 根据编译器支持的内容为请求的 C++ 标准设置适当的编译器标志,或者如果它不支持请求的标准则出错。
还应注意,CMake 可能会升级目标以使用比其 CXX_STANDARD
目标 属性 指定的语言标准更新的语言标准。使用 compile feature requirements (如@FlorianWolters 回答中所述)可以提高语言标准要求。事实上,CMake 将始终选择由 CXX_STANDARD
目标 属性 或目标上设置的编译功能要求指定的更强的语言要求。另请注意,早期版本的 CMake 文档并未准确反映 CXX_EXTENSIONS
与编译功能交互的方式。对于 CMake 3.21 或更早版本,CXX_EXTENSIONS
仅在还指定了 CXX_STANDARD
时才会生效,对于大多数常见的编译器(因为它们与一个编译器标志一起指定)。从 CMake 3.22 开始,无论 CXX_STANDARD
是否设置,CXX_EXTENSIONS
都被尊重。
现代 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)
请参阅 cmake-compile-features 的官方 CMake 文档中的 需要语言标准 部分以了解更多信息。