首页 文章

如何在CMake中激活C 11?

提问于
浏览
308

当我尝试运行CMake生成的makefile来编译我的程序时,我得到了错误

C 98模式不支持>基于范围的循环 .

我尝试将 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功能 .

13 回答

  • 176

    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用户发布#15943问题

    如果你使用CMake和clang来定位MacOS,那么bug会导致 CMAKE_CXX_STANDARD 功能根本不起作用(不添加任何编译器标志) . 确保您执行以下操作之一:

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

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

    # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS.
    if (POLICY CMP0025)
      cmake_policy(SET CMP0025 NEW)
    endif ()
    
  • 15

    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 之外的其他C功能 . CMake全局属性CMAKE_CXX_KNOWN_FEATURES列出了您可以选择的C功能 .

    您也可以通过为CMake目标设置CMake属性CXX_STANDARDCXX_STANDARD_REQUIRED来明确指定C标准,而不是使用 target_compile_features() .

    另见my more detailed answer .

  • 38

    我在用

    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++ 版本 .

  • 23

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

    set_property(TARGET tgt PROPERTY CXX_STANDARD 11)
    

    有关详细信息,请参阅the CMake documentation .

  • 6

    事实证明, 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")
    
  • 3

    最简单的方法:

    add_compile_options(-std=c++11)

  • 2

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

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

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

  • 321

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

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

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

  • 90

    对于CMake 3.8和更新版本,您可以使用

    target_compile_features(target PUBLIC cxx_std_11)
    
  • 50

    我认为这两条线就足够了 .

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

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

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

    它转换为“我想要所有目标的C 11,它不是可选的,我不想使用任何GNU或MS扩展 . ”截至第17页,这仍然是恕我直言的最佳方式 .

    资料来源:https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/

  • 0

    如果您想要始终激活最新的C标准,这里是我的David Grayson's answer的扩展,根据最近(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() # CMake 3.11 or higher:
        SET(CMAKE_CXX_STANDARD 20)
    ENDIF()
    # Typically, you'll also want to turn off compiler-specific extensions:
    SET(CMAKE_CXX_EXTENSIONS OFF)
    

    (在链接的anwswer中使用该代码代替 set (CMAKE_CXX_STANDARD 11) ) .

  • 6

    OS X和Homebrew LLVM相关:

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

    或者CMake将在第1行之前隐式插入 project() ,导致Clang版本检测出现问题,并可能出现其他类型的问题 . 这是a related issue .

相关问题