386

当我尝试运行 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-9ubuntu3) 4.6.1

我也试过SET(CMAKE_CXX_FLAGS "-std=c++0x")了,还是不行。

我不明白如何使用 CMake 激活 C++ 11 功能。

4

15 回答 15

444

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,但应该可以直接将其扩展到其他编译器。

use_cxx11()然后,您可以在任何定义使用 C++11 的目标的 CMakeLists.txt 文件的顶部编写代码。

针对 macOS 的 clang 用户的 CMake 问题 #15943

如果您使用 CMake 和 clang 来定位 macOS,则存在可能导致该功能无法正常工作的错误(不添加任何编译器标志)。CMAKE_CXX_STANDARD确保您执行以下操作之一:

  • 使用cmake_minimum_required要求 CMake 3.0 或更高版本,或

  • 在命令前的 CMakeLists.txt 文件顶部使用以下代码将策略 CMP0025 设置为 NEW project

      # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
      if (POLICY CMP0025)
        cmake_policy(SET CMP0025 NEW)
      endif ()
    
于 2015-06-23T18:05:27.910 回答
191

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++ 程序使用了除cxx_range_for. CMake 全局属性CMAKE_CXX_KNOWN_FEATURES列出了您可以选择的 C++ 功能。

除了使用target_compile_features(),您还可以通过设置 CMake 属性 CXX_STANDARDCXX_STANDARD_REQUIREDCMake 目标来明确指定 C++ 标准。

另请参阅我更详细的答案

于 2013-11-23T17:27:43.677 回答
93

我在用

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

但是如果你想玩C++11g++ 4.6.1已经很老了。尝试获取更新的g++版本。

于 2014-09-14T19:04:46.900 回答
60

设置 Cxx 标准的最简单方法是:

 set_property(TARGET tgt PROPERTY CXX_STANDARD 11)

有关更多详细信息,请参阅CMake 文档

于 2015-05-15T03:50:23.230 回答
42

事实证明,SET(CMAKE_CXX_FLAGS "-std=c++0x")它确实激活了许多 C++11 特性。它不起作用的原因是该语句看起来像这样:

set(CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")

按照这种方法,不知何故该-std=c++0x标志被覆盖并且它不起作用。一个一个地设置标志或使用列表方法是有效的。

list( APPEND CMAKE_CXX_FLAGS "-std=c++0x ${CMAKE_CXX_FLAGS} -g -ftest-coverage -fprofile-arcs")
于 2012-06-01T14:59:31.140 回答
38

在现代 CMake (>= 3.1) 上,设置全局要求的最佳方法是:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

它翻译为“我希望所有目标都使用 C++11,它不是可选的,我不想使用任何 GNU 或 Microsoft 扩展。” 从 C++17 开始,这仍然是恕我直言的最佳方式。

资料来源:在 CMake 中启用 C++11 及更高版本

于 2018-09-18T08:42:28.957 回答
32

对于 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)

这在An Introduction to Modern CMake -> 添加功能 -> C++11 and Beyond 中有详细记录。如果您受到限制,它还提供了有关如何在旧版本的 CMake 上实现这一点的建议。

于 2018-04-01T11:37:27.343 回答
20

最简单的方法:

add_compile_options(-std=c++11)

于 2016-02-22T11:17:54.170 回答
15

这是启用 C++11 支持的另一种方式,

ADD_DEFINITIONS(
    -std=c++11 # Or -std=c++0x
    # Other flags
)

我遇到过只有这种方法有效而其他方法失败的情况。也许它与最新版本的 CMake 有关。

于 2013-05-06T06:52:33.367 回答
6

如果您想始终激活最新的 C++ 标准,根据最近(CMake 3.8 和 CMake 3.11)为 CMAKE_CXX_STANDARD 增加的值 17 和 20 ,这是我对David Grayson 答案的扩展:

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)链接答案中的 。)

于 2018-12-06T18:28:04.557 回答
6

现代 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
    )
于 2020-04-17T21:51:11.553 回答
4

对我有用的是在 CMakeLists.txt 中设置以下行:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

设置此命令会激活编译器的 C++11 功能,执行该cmake ..命令后,您应该能够range based for loops在代码中使用并编译它而不会出现任何错误。

于 2016-08-01T08:27:28.463 回答
3

我认为只有这两行就足够了。

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
于 2018-06-13T09:36:10.637 回答
0

您可以使用以下内容。这会根据您的环境自动修改功能。

target_compile_features(your_target INTERFACE cxx_std_20)

例如,

  • 在 Gnu/Linux 上添加以下内容-std=gnu++20
  • 在带有 Clang/Ninja 的 Windows 上,它变成-std=c++20
  • 在带有 MSVC 的 Windows 上,它变成/std=c++20

因此,您支持尽可能多的环境。

于 2021-11-02T01:48:28.770 回答
-6

OS X 和 Homebrew LLVM 相关:

不要忘记在它之后调用 cmake_minimum_required(VERSION 3.3) 和 project() !

或者 CMake 将project()在第 1 行之前隐式插入,从而导致 Clang 版本检测问题以及可能的其他类型的问题。这是一个相关的问题

于 2016-01-29T16:46:19.367 回答