【问题标题】:How to enable C++17 in CMake如何在 CMake 中启用 C++17
【发布时间】:2018-01-23 02:51:10
【问题描述】:

我使用的是支持集成 CMake 3.8 的 VS 15.3。如何在不为每个特定编译器编写标志的情况下以 C++17 为目标?我当前的全局设置不起作用:

# https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# expected behaviour
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++lastest")

我希望 CMake 在生成 VS 解决方案文件时添加“/std:c++lastest”或等效项,但没有找到 c++17 标志,导致编译器错误:

C1189 #error: class template optional is only available with C++17.

【问题讨论】:

  • CMake 通常不会消除为每个特定编译器编写标志的需要。
  • “VS 15.3”是指 Visual Studio 2017 预览版 3 吗?或者你的意思是 Visual Studio 2015 更新 3(它不支持太多,如果有的话,C++17)?
  • @Someprogrammerdude 我正在使用std::optional 功能,如果我手动将"/std:c++lastest" 标志添加到CMakeLists,就可以使用。
  • 您需要将标志传递给编译器。接受 C++17 的是 编译器,而不是 cmake
  • 是最新的,不是最新的

标签: c++ visual-studio cmake c++17


【解决方案1】:

现代 CMake 为此提出了一个接口target_compile_features。 文档在这里:Requiring Language Standards

像这样使用它:

target_compile_features(${TARGET_NAME} PRIVATE cxx_std_17)

【讨论】:

  • @vitaut 你能解释一下为什么将 ${PROJECT_NAME} 重命名为 ${TARGET_NAME} 吗?
  • Project 在 CMake 中有不同的含义:cmake.org/cmake/help/v3.0/command/project.htmltarget_compile_features 适用于目标。
  • 所以为了清楚起见我改变了它。随时恢复。
  • 我希望接受的答案会随着新语言功能的出现而自动更改...这是正确的答案。上面的都已经很过时了。
  • 在 CMake 中,PUBLIC(适用于所有人)=INTERFACE(适用于其他人)+PRIVATE(适用于我)
【解决方案2】:

您的方法是正确的,但它不适用于 MSVC 在 3.10 之前的 CMake 版本上。

来自CMake 3.9 documentation

对于没有标准级别概念的编译器,例如 MSVC,这不起作用。

简而言之,CMake 尚未更新以适应添加到 VC++ 2017 的标准标志。

您现在必须检测是否使用了 VC++ 2017(或更高版本)并自己添加相应的标志。


在 CMake 3.10(及更高版本)中,此问题已针对较新版本的 VC++ 进行了修复。见the 3.10 documentation

【讨论】:

  • 较新的 CMake 3.10(及更高版本)文档说它适用于 Visual Studio 2015 更新 3 或更新版本。仅不支持 2015 Update 3 之前的 Visual Studio 版本。上面的链接实际上指向了反映这一点的最新文档。
  • @Marcus10110 正确,将链接更改为指向 3.9 文档。并添加了关于它已针对较新版本进行修复的说明。谢谢。
  • 一个(可能)迂腐评论:要使 MSVC 表现得像一个符合标准的编译器,您还必须使用 /Zc:__cplusplus 标志,因为否则 __cplusplus 宏未设置为正确的值。一个肯定迂腐的评论是我认为这是 cmake 中的一个错误:当我要求 C++11、C+14、C++17 时,我希望 cmake 设置制作所需的 all 标志编译器符合,其中包括 __cplusplus 宏的值。
【解决方案3】:

在现代 CMake 中,我发现最好在目标级别而不是全局变量级别分配 CXX 标准,并使用内置属性(参见此处:https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html)使其与编译器无关。

例如:

set_target_properties(FooTarget PROPERTIES
            CXX_STANDARD 17
            CXX_EXTENSIONS OFF
            etc..
            )

【讨论】:

  • 根据文档,CXX_STANDARD_REQUIRED 是一个布尔值。 cmake.org/cmake/help/v3.10/prop_tgt/CXX_STANDARD_REQUIRED.html
  • “现代”CMake 究竟是什么意思?
  • 似乎每个 cmake 功能都会立即过时,互联网上充斥着过时的问题和答案。
  • “现代 CMake”在 Craig Scott 的书中有所描述。在此过程中进行了许多重新思考,导致脚本更加关注抽象目标,而不是硬塞编译器标志等。在这里查看他的书:crascit.com/professional-cmake
【解决方案4】:

您可以将 set(CMAKE_CXX_STANDARD 17) 保留给其他编译器,例如 Clang 和 GCC。但是对于 Visual Studio 来说,它是没用的。

如果 CMake 仍然不支持这一点,您可以对 Visual Studio 执行以下操作:

if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17")
endif(MSVC)

编辑:由于问题标题没有提到编译器,让我为 gccclang 和类似的编译器补充一下,这个是启用C++17的命令:

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

【讨论】:

  • Recent VS changes 允许使用/std:c++14/std:c++17/std:c++latest 标志设置标准。
  • 我的情况正好相反。我正在使用 CMake 3.19.1、VS2019 和 gcc 7.5.0。 set(CMAKE_CXX_STANDARD 17) 对于 VS2019 来说已经足够了,但是 gcc 需要 target_compile_features(${TARGET_NAME} PRIVATE cxx_std_17)。即使是明确的add_compile_options("-std=gnu++17") 也是不够的。
【解决方案5】:

当使用vs2019

set(CMAKE_CXX_STANDARD 17)

【讨论】:

  • 它正在工作。谢谢。
【解决方案6】:

根据我的测试,以下代码将使VS2019能够选择/std:c++latest,否则对于其他平台它将C++版本设置为C++17。我已经用 emscripten、raspbian 和 windows 对此进行了测试。

if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest")
else(MSVC)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)
endif(MSVC)

【讨论】:

  • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
【解决方案7】:

您还可以使用 target_compile_options 为 Visual Studio 2019 设置 /std:c++latest 标志

if (MSVC_VERSION GREATER_EQUAL "1900")
    include(CheckCXXCompilerFlag)
    CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported)
    if (_cpp_latest_flag_supported)
        target_compile_options(${TARGET_NAME} PRIVATE "/std:c++latest")
    endif()
endif()

${TARGET_NAME} 替换为实际的目标名称。

【讨论】:

    【解决方案8】:

    CMake 标志中的 Bash 命令行:

    -DCMAKE_CXX_STANDARD=17 \
    -DCMAKE_CXX_STANDARD_REQUIRED=ON \
    -DCMAKE_CXX_EXTENSIONS=OFF \
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-29
      • 1970-01-01
      • 2018-11-04
      • 2021-03-30
      • 2017-05-09
      相关资源
      最近更新 更多