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 顺便提一下,我复制的解决方案无法考虑
/Wall
选项,这也与/W4
不兼容。
答案 0 :(得分:23)
编译器的默认设置是从位于CMake安装的Modules
目录中的标准模块文件中获取的。使用的实际模块文件取决于平台和编译器。例如,对于Visual Studio 2017,CMake将从文件Windows-MSVC.cmake
加载默认设置,并从Windows-MSVC-C.cmake
或Windows-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()
然后初始化CMakeLists.txt
中的CMAKE_USER_MAKE_RULES_OVERRIDE变量:
# 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)
在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
以重新创建构建文件夹。
答案 1 :(得分:5)
将我的评论转化为答案
CMake确实预装了一些编译器开关。对于visual studio,主要是标准链接库,警告级别,优化级别,异常处理,调试信息和特定于平台的定义。
当您想要更改CMake生成的编译器设置时,您现在要区分的是以下用例:
因此,让我们讨论这些案例的常见解决方案。
标准方法是使用CMake附带的工具(如cmake-gui
和ccmake
)修改缓存的编译器标记变量。
要在Visual Studio中实现此目的,您必须:
CMake / Cache / View CMakeCache
手动更改,例如CMAKE_CXX_FLAGS
至/Wall
<强> CMakeCache.txt 强>
//Flags used by the compiler during all build types.
CMAKE_CXX_FLAGS:STRING= /DWIN32 /D_WINDOWS /Wall /GR /EHsc
CMake / Cache / Generate
或者您通过CMAKE_CXX_FLAGS
文件预设CMakeSettings.json
缓存变量:
CMake / Change CMake Settings
在-DCMAKE_CXX_FLAGS:STRING=...
cmakeCommandArgs
的缓存条目
<强> CMakeSettings.json 强>
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug (all warnings)",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_CXX_FLAGS:STRING=\"/DWIN32 /D_WINDOWS /Wall /GR /EHsc\"",
"buildCommandArgs": "-m -v:minimal"
}
]
}
如果您将此CMakeSettings.json
文件与CMake项目一起提供,则会永久
如果你想保留大部分CMake的编译器标志,@ sakra的回答肯定是要走的路。
对于我的VS项目,我已将CXX标志设置放入项目本身附带的工具链文件中。主要是冻结这些设置,并且不使用CMake版本或任何环境变量设置依赖。
以上面的例子为例:
<强> VS2017Toolchain.cmake 强>
set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /Wall /GR /EHsc" CACHE INTERNAL "")
<强> CMakeSettings.json 强>
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug (all warnings)",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=\"${projectDir}\\VS2017Toolchain.cmake\"",
"buildCommandArgs": "-m -v:minimal"
}
]
}
答案 2 :(得分:0)
在CMake 3.15中,CMake针对此MSVC特定警告引入了fix:
cl : Command line warning D9025: overriding '/W3' with '/W4'
和编译器警告标志(如/W3
)不再自动添加。因此,通过升级到CMake 3.15或更高版本,此警告将不再出现。从文档中:
在CMake 3.14及更低版本中使用类似MSVC的编译器时,默认情况下,将
/W3
之类的警告标志添加到CMAKE_<LANG>_FLAGS
中。对于希望以编程方式选择其他警告级别的项目而言,这是个问题。特别是,它需要使用CMake内置默认值的知识来对CMAKE_<LANG>_FLAGS
变量进行字符串编辑,以便可以替换它们。CMake 3.15及更高版本更喜欢默认情况下从
CMAKE_<LANG>_FLAGS
的值中删除警告标志。
与此修复程序一起,CMake引入了策略CMP0092,该策略可让您在必要时切换回OLD
行为(默认情况下添加警告标志)。