【问题标题】:How to enable /std:c++17 in VS2017 with CMake如何使用 CMake 在 VS2017 中启用 /std:c++17
【发布时间】:2017-07-07 00:24:15
【问题描述】:

我正在尝试使用 CMake 将 /std:c++17 编译器标志添加到 VS2017。到目前为止,我使用的是“现代”跨平台方式:

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # -std=c++11 instead of -std=gnu++11
set(MY_CXX_COMPILE_FEATURES cxx_generic_lambdas cxx_range_for cxx_strong_enums)

add_library(mylib INTERFACE)
target_compile_features(mylib INTERFACE ${MY_CXX_COMPILE_FEATURES})

这会在 VS2017 中添加 /std:c++14(这可能是默认值?)。 但是,我无法将其切换到 C++17(即添加/std:c++17)。如果我只是手动添加它,我会收到不太好的警告,因为两个标志都存在:

1>cl : Command line warning D9025: overriding '/std:c++14' with '/std:c++17'

我试过set(CMAKE_CXX_STANDARD 17)但是没有效果,事实上CMake文档提到CMAKE_CXX_STANDARD无论如何对VS没有影响。

至于在target_compile_features 中添加 C++17 功能,似乎还没有(即使在 CMake-3.9.0-rc5 中),即使有,我也只是使用来自 C++17 的 std::optional,并且没有 target_compile_features 标志用于库功能,如 std::optional

所以我的问题是,用 CMake 做到这一点最好(或最不丑)的方法是什么?在某种程度上,它也适用于 gcc 和 clang?我很高兴使用最新的 CMake 版本(3.8 或 3.9)。我更喜欢它“不错”,而不是手动循环遍历 CXX_COMPILE_FLAGS 并删除字符串“/std:c++14”或类似的黑客攻击。

编辑:它也可以是 VS/std:c++latest 开关——只要可能。两者都可以达到目的。)

【问题讨论】:

  • gitlab.kitware.com/cmake/cmake/issues/16482,这是正在进行的工作。
  • 更新:CMAKE_CXX_STANDARD 17 现在可以在最新的 CMake nightly 中使用,并将登陆 CMake-3.10。
  • @Ela782 随着时间的流逝,您是否可以考虑接受我的答案,因为我相信它是最新的。
  • @tambre 对此的 SO 政策是什么?当时接受的答案是正确的。在这种特殊情况下,我倾向于同意您的观点并更改已接受的答案。 @Florian 有什么想法吗?
  • @Ela782 您(提问者)稍后接受另一个答案是完全可以接受的。见here

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


【解决方案1】:

把我的评论变成答案

  1. CMake 团队正在为 VS2017 开发(截至 2017 年 7 月,即将发布的 CMake 版本 3.10):

    CMake: MSVC standard version switches

    那些标志似乎是相当新的开关(与这个问题的日期有关):

    VS 2017 15.3 预览版现在支持 /std:c++17

    因此,对于 Visual Studio,您必须“手动”替换或附加编译器开关,直到 CMake 正式支持它。

    这是我为std:c++latest 测试过的代码 sn-p(例如在我的 CMake 3.8.0 版本中已经支持):

    if (MSVC_VERSION GREATER_EQUAL "1900")
        include(CheckCXXCompilerFlag)
        CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported)
        if (_cpp_latest_flag_supported)
            add_compile_options("/std:c++latest")
        endif()
    endif()
    
  2. 对于 CLang 和 GNU,该支持从 2017 年开始并入主源代码分支,并且是 CMake 3.8 及更高版本的一部分:

    CMake: Features: Add support for C++ 17 language standard

【讨论】:

  • 嗯!太糟糕了,还没有登陆 CMake,这个问题已经 7 个月了 :-( (这些标志并不是真的太新,VS2015 已经有了它们)。无论如何。鉴于我使用的是“现代”和基于目标的方法,手动替换/添加 MSVC 标志的最佳方法是什么?
  • 我觉得这会很头疼。我不能 get_target_property(my_compile_flags mylib COMPILE_FLAGS) 因为它是一个 INTERFACE 目标(仅标头库)...
  • 我在一个新问题中提出了这个问题:stackoverflow.com/questions/44977868/…
  • @Ela782 添加了应该作为全局设置工作的代码 sn-p。只是不要将任何CMAKE_CXX_STANDARD 定义与其并行(以避免在生成的项目文件中发生冲突)。
  • 有了add_compile_options,我们可以传递任何我们想要的东西,所以这实际上并不有趣。有没有办法以便携的方式设置/std:c++latest,例如CMAKE_CXX_STANDARD?
【解决方案2】:

高于 3.10 support MSVC C++ standard switches 的 CMake 版本适用于高于 19.0.24215 的 MSVC 版本。如果任一版本要求不满足,则它们无效。

要确保您的程序在 Visual Studio 上使用正确的 C++ 标准模式编译,唯一可移植的方法是至少需要 CMake 3.10,将目标属性 CXX_STANDARD 设置为您想要的值,将 CXX_STANDARD_REQUIRED 设置为 @987654329 @。

示例用法:

set_property(TARGET my_target PROPERTY CXX_STANDARD 17)
set_property(TARGET my_target PROPERTY CXX_STANDARD_REQUIRED ON)

【讨论】:

  • 有没有办法用它设置/std:c++latest
  • @Mikhail No. Consensus here 似乎不会为CXX_STANDARD 添加LATEST 值,而是分别支持每个标准版本。我创建了 an issue 来添加 C++2a 支持。
  • @Mikhail 对 C++20 的支持现在位于 CMake nightlies。介意试试吗?
  • 一点更新,使用 CMake 3.14.3 和 VS2019,我所要做的就是在我的 CMakeLists.txt 文件中set(CMAKE_CXX_STANDARD 17)
猜你喜欢
  • 2021-03-01
  • 2018-01-23
  • 2023-01-17
  • 2021-01-02
  • 1970-01-01
  • 2017-01-14
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
相关资源
最近更新 更多