Skip to main content
 首页 » 编程设计

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

2025年04月02日21www_RR

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菜单以重新创建构建文件夹。