当我试图运行一个CMake生成的makefile来编译我的程序时,我得到的错误是
c++ 98模式不支持基于范围的for循环。
我尝试添加add_definitions(-std=c++0x)到我的CMakeLists.txt,但它没有帮助。
我也试过这个:
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=gnu++0x)
endif()
当我执行g++——version时,我得到:
g+ (Ubuntu/Linaro 4.6.1- 9u阑尾3)4.6.1
我还尝试了SET(CMAKE_CXX_FLAGS "-std=c++0x"),这也不起作用。
我不明白如何使用CMake激活c++ 11特性。
CMake命令target_compile_features()用于指定所需的c++特性cxx_range_for。然后,CMake将引入要使用的c++标准。
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(foobar CXX)
add_executable(foobar main.cc)
target_compile_features(foobar PRIVATE cxx_range_for)
不需要使用add_definitions(-std=c++11)或修改CMake变量CMAKE_CXX_FLAGS,因为CMake将确保使用适当的命令行标志调用c++编译器。
也许你的c++程序使用了其他c++特性而不是cxx_range_for。CMake全局属性CMAKE_CXX_KNOWN_FEATURES列出了你可以选择的c++特性。
除了使用target_compile_features(),你还可以通过设置CMake属性显式地指定c++标准
CXX_STANDARD
而且
你的CMake目标的CXX_STANDARD_REQUIRED。
请参见我更详细的回答。
CMake 3.1引入了可以使用的CMAKE_CXX_STANDARD变量。如果你知道你总是有CMake 3.1或更高版本可用,你可以把它写在你的顶级CMakeLists.txt文件中,或者把它放在任何新目标定义之前:
set (CMAKE_CXX_STANDARD 11)
如果你需要支持旧版本的CMake(现在不太可能),这里有一个我想到的宏,你可以使用:
macro(use_cxx11)
if (CMAKE_VERSION VERSION_LESS "3.1")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
endif ()
else ()
set (CMAKE_CXX_STANDARD 11)
endif ()
endmacro(use_cxx11)
宏目前只支持GCC,但是将其扩展到其他编译器应该很简单。
然后,您可以在任何CMakeLists.txt文件的顶部编写use_cxx11(),该文件定义了使用c++ 11的目标。
针对macOS的clang用户的CMake issue #15943
如果你使用CMake和clang来瞄准macOS,有一个错误可以导致CMAKE_CXX_STANDARD特性根本不能工作(不添加任何编译器标志)。确保你做了以下其中一件事:
使用cmake_minimum_required来要求CMake 3.0或更高版本,或者
在项目命令之前,在CMakeLists.txt文件的顶部使用以下代码将策略CMP0025设置为NEW:
修复CMAKE_CXX_STANDARD在针对macOS时的行为。
if (POLICY CMP0025)
设置CMP0025 NEW
endif ()
对于CMake 3.8和更新版本,您可以使用
target_compile_features(target PUBLIC cxx_std_11)
如果您希望在工具链不能遵循此标准的情况下生成步骤失败,则可以将此设置为必需的。
set_target_properties(target PROPERTIES CXX_STANDARD_REQUIRED ON)
如果你想严格遵守标准c++,即避免你的编译器提供的c++扩展(如GCC的-std=gnu++17),另外设置
set_target_properties(target PROPERTIES CXX_EXTENSIONS OFF)
这是在现代CMake介绍->添加功能-> c++ 11和超越详细文档。它还提供了关于如何在旧版本的CMake上实现这一点的建议,如果你受到限制的话。
如果你想总是激活最新的c++标准,这里是我对David Grayson的答案的扩展,根据最近(CMake 3.8和CMake 3.11)为CMAKE_CXX_STANDARD增加了17和20的值:
IF (CMAKE_VERSION VERSION_LESS "3.8")
SET(CMAKE_CXX_STANDARD 14)
ELSEIF (CMAKE_VERSION VERSION_LESS "3.11")
SET(CMAKE_CXX_STANDARD 17)
ELSE()
SET(CMAKE_CXX_STANDARD 20)
ENDIF()
# Typically, you'll also want to turn off compiler-specific extensions:
SET(CMAKE_CXX_EXTENSIONS OFF)
(在链接答案中的set (CMAKE_CXX_STANDARD 11)中使用该代码。)
现代cmake提供了更简单的方法来配置编译器以使用特定版本的c++。所有人需要做的唯一一件事就是设置相关的目标属性。在cmake支持的属性中,用于确定如何配置编译器以支持特定版本的c++的属性如下:
CXX_STANDARD设置c++标准,它的特性被请求来构建目标。将此值设置为11,以目标c++ 11。
CXX_EXTENSIONS,一个布尔值,指定是否请求特定于编译器的扩展。将此设置为Off将禁用对任何特定于编译器的扩展的支持。
为了演示,这里有一个CMakeLists.txt的最小工作示例。
cmake_minimum_required(VERSION 3.1)
project(testproject LANGUAGES CXX )
set(testproject_SOURCES
main.c++
)
add_executable(testproject ${testproject_SOURCES})
set_target_properties(testproject
PROPERTIES
CXX_STANDARD 11
CXX_EXTENSIONS off
)
现代的方法是通过以下方式指定c++ 11所需的最低标准:
target_compile_features(foo PUBLIC cxx_std_11)
这种方式:
CMake can honor default C++ standard of the compiler if it's greater than C++11
You can clearly specify whether C++ standard is required at build time, consume time, or both. This is nice for libraries.
Public compile features are propagated to downstream targets, so it comes for free in those targets even if they don't directly use this feature.
Users can externally set another C++ standard (more recent basically), with CMAKE_CXX_STANDARD, either from command line or CMake presets. If you hardcode CMAKE_CXX_STANDARD in a CMakeLists, nobody can override the C++ standard without editing your CMakeLists, which is not very pleasant.
它需要CMake >= 3.8