visual-c++ - 如何在 Visual Studio 2017 中使用 CMake 设置编译器选项

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

Visual Studio 2017 带有完整的 CMake 集成。为了了解这种组合,我从这个基本示例开始:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(foo)
add_executable(foo foo.cpp)


// foo.cpp
int main() {}

这会正确生成构建脚本,并且可以毫无问题地编译和链接。那很简单。

另一方面,尝试设置编译器选项并非易事。就我而言,我试图将警告级别设置为 4。

显而易见的解决方案
add_compile_options("/W4")

没有像预期的那样成功。传递给编译器的命令行现在包含 /W4 (按预期)以及/W3 (从其他地方捡起),产生以下警告:

cl : Command line warning D9025: overriding '/W3' with '/W4'


要解决这个问题,我需要替换任何不兼容的编译器选项,而不仅仅是添加一个。 CMake 没有为此提供任何即时支持,标准解决方案(如 this Q&A suggests )似乎是:
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
endif()

然而,这有两个问题:
  • 它集全局CMAKE_CXX_FLAGS ,适用于所有 C++ 目标。这可能不是故意的(现在对我来说不是问题)。
  • 它没有规模。对于要添加的每个编译器选项,您都必须阅读不兼容的选项,然后先手动删除这些选项。这将不可避免地失败1。

  • 我的问题有两个:
  • CMake 集成从哪里获取默认设置,这可以控制吗?
  • 一般如何设置编译器选项? (如果这个话题太宽泛,我很乐意仅在设置警告级别方面提供帮助。)

  • 1 顺便说一句,我复制的解决方案无法解释 /Wall选项,与 /W4 不兼容也是。

    最佳答案

    编译器的默认设置取自位于 Modules 中的标准模块文件。 CMake 安装目录。实际使用的模块文件取决于平台和编译器。例如,对于 Visual Studio 2017,CMake 将从文件 Windows-MSVC.cmake 加载默认设置。和语言特定设置来自 Windows-MSVC-C.cmakeWindows-MSVC-CXX.cmake .
    要检查默认设置,请创建文件 CompilerOptions.cmake在项目目录中包含以下内容:

    # log all *_INIT variables
    get_cmake_property(_varNames VARIABLES)
    list (REMOVE_DUPLICATES _varNames)
    list (SORT _varNames)
    foreach (_varName ${_varNames})
        if (_varName MATCHES "_INIT$")
            message(STATUS "${_varName}=${${_varName}}")
        endif()
    endforeach()
    
    然后初始化 CMAKE_USER_MAKE_RULES_OVERRIDE CMakeLists.txt 中的变量:
    # CMakeLists.txt
    cmake_minimum_required(VERSION 3.8)
    set (CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_LIST_DIR}/CompilerOptions.cmake")
    project(foo)
    add_executable(foo foo.cpp)
    
    在使用 Open Folder 打开目录时配置项目时在 Visual Studio 2017 中,IDE 的输出窗口中将显示以下信息:
     ...
     -- CMAKE_CXX_FLAGS_DEBUG_INIT= /MDd /Zi /Ob0 /Od /RTC1
     -- CMAKE_CXX_FLAGS_INIT= /DWIN32 /D_WINDOWS /W3 /GR /EHsc
     -- CMAKE_CXX_FLAGS_MINSIZEREL_INIT= /MD /O1 /Ob1 /DNDEBUG
     -- CMAKE_CXX_FLAGS_RELEASE_INIT= /MD /O2 /Ob2 /DNDEBUG
     -- CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT= /MD /Zi /O2 /Ob1 /DNDEBUG
     ...
    
    所以警告设置/W3取自 CMake 变量 CMAKE_CXX_FLAGS_INIT然后适用于项目中生成的所有 CMake 目标。
    要控制 CMake 项目或目标级别的警告级别,可以更改 CMAKE_CXX_FLAGS_INIT CompilerOptions.cmake 中的变量通过将以下行添加到文件中:
    if (MSVC)
        # remove default warning level from CMAKE_CXX_FLAGS_INIT
        string (REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT}")
    endif()
    
    然后可以通过在 CMakeLists.txt 中设置目标编译选项来控制警告标志。 :
    ...
    add_executable(foo foo.cpp)
    target_compile_options(foo PRIVATE "/W4")
    
    对于大多数 CMake 项目,控制规则覆盖文件中的默认编译器选项而不是手动调整变量(如 CMAKE_CXX_FLAGS)是有意义的。 .
    更改 CompilerOptions.cmake 时文件,有必要重新创建构建文件夹。在 Open Folder 中使用 Visual Studio 2017 时模式,选择命令Cache ... -> Delete Cache Folders来自 CMake菜单,然后 Cache ... -> Generate来自 CMake菜单以重新创建构建文件夹。

    关于visual-c++ - 如何在 Visual Studio 2017 中使用 CMake 设置编译器选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45995784/

    相关文章:

    Visual Studio Express 2015 中的 C++ 新文件问题

    c++ - 重写嵌套类并将外部类作为基类返回是否合法?

    c++ - 如何遍历包含 3 个值的二维数组并检查这些值?

    c++ - 运算符(operator)的 MSVC 错误 |

    c++ - aarch64 动态链接器 rpath 使用与辅助依赖链接

    qt - CMake 如何知道要使用哪个版本的 Qt?

    c# - Microsoft 命名空间中不存在 ApplicationInsight

    git - 使用 Visual Studio 2017 克隆 TFS Git 存储库时出现错误 400

    mysql - VS 2017 和 MySQL : Updated MySQL. 数据到 8.0.11.0 并且我的查询都不起作用

    c++ - Cmake 是如何查找文件的?