如何使用CMake在VS2017中启用/ std:c ++ 17

时间:2017-07-07 00:24:16

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

我正在尝试使用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开关 - 以可能的为准。两者都有用。)

2 个答案:

答案 0 :(得分:18)

将我的评论转化为答案

  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测试的代码段(已在我的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

答案 1 :(得分:13)

对于比19.0.24215更新的MSVC版本,CMake版本高于3.10 support MSVC C++ standard switches。如果未满足任一版本要求,则它们无效。

确保在Visual Studio上使用正确的C ++标准模式编译程序的唯一可移植方法是至少要求CMake 3.10,将目标属性CXX_STANDARD设置为所需的值{{3} } ON

使用示例:

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