IIn*_*ble 21 cmake visual-c++ visual-studio-2017
Visual Studio 2017提供完整的CMake集成.要了解这个组合,我从这个基本样本开始:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(foo)
add_executable(foo foo.cpp)
Run Code Online (Sandbox Code Playgroud)
和
// foo.cpp
int main() {}
Run Code Online (Sandbox Code Playgroud)
这正确地生成了构建脚本,并且编译和链接没有任何问题.那很简单.
另一方面,试图设置编译器选项,结果却是微不足道的.在我的情况下,我试图将警告级别设置为4.
明显的解决方案
add_compile_options("/W4")
Run Code Online (Sandbox Code Playgroud)
没有像预期的那样平息.传递给编译器的命令行现在既包含/W4(按预期),也包含/W3(从其他地方获取),产生以下警告:
Run Code Online (Sandbox Code Playgroud)cl : Command line warning D9025: overriding '/W3' with '/W4'
要解决这个问题,我需要替换任何不兼容的编译器选项,而不是只添加一个.CMake没有为此提供任何直接支持,标准解决方案(正如此问答所示)似乎是:
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()
Run Code Online (Sandbox Code Playgroud)
然而,这有两个问题:
CMAKE_CXX_FLAGS,适用于所有C++目标.这可能不是有意的(现在对我来说不是问题).我的问题是双重的:
/Wall选项,这也是不兼容的/W4.
sak*_*kra 25
编译器的默认设置是从位于ModulesCMake安装目录中的标准模块文件中获取的.使用的实际模块文件取决于平台和编译器.例如,为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()
Run Code Online (Sandbox Code Playgroud)
然后在您的:中初始化CMAKE_USER_MAKE_RULES_OVERRIDE变量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)
Run Code Online (Sandbox Code Playgroud)
在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
...
Run Code Online (Sandbox Code Playgroud)
因此,警告设置CMakeLists.txt从CMake变量中获取/W3,然后应用于项目中生成的所有CMake目标.
要控制CMake项目或目标级别的警告级别,可以通过在文件中添加以下行来更改CMAKE_CXX_FLAGS_INIT变量CMAKE_CXX_FLAGS_INIT:
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()
Run Code Online (Sandbox Code Playgroud)
然后可以通过在以下位置设置目标编译选项来控制警告标志CompilerOptions.cmake:
...
add_executable(foo foo.cpp)
target_compile_options(foo PRIVATE "/W4")
Run Code Online (Sandbox Code Playgroud)
对于大多数CMake项目,控制覆盖文件中的默认编译器选项是有意义的,而不是手动调整变量等CMakeLists.txt.
在对CMAKE_CXX_FLAGS文件进行更改时,必须重新创建构建文件夹.在CompilerOptions.cmake模式下使用Visual Studio 2017时,Open Folder从Cache ... -> Delete Cache Folders菜单中选择命令,然后CMake从Cache ... -> Generate菜单中重新创建构建文件夹.
把我的评论变成答案
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
Run Code Online (Sandbox Code Playgroud)CMake / Cache / Generate
或者,您CMAKE_CXX_FLAGS通过CMakeSettings.json文件预设了缓存变量:
CMake / Change CMake Settings
用-DCMAKE_CXX_FLAGS:STRING=...in 强制缓存条目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"
}
]
}
Run Code Online (Sandbox Code Playgroud)如果您CMakeSettings.json随CMake项目一起提供此文件,它将永久保存
如果您想保留大多数CMake的编译器标志,@ sakra的答案肯定是正确的方法。
对于我的VS项目,我将CXX标志设置放入了项目本身随附的工具链文件中。主要是冻结那些设置,并且不依赖于所使用的CMake版本或任何环境变量集。
从上面的示例中可以看到:
VS2017工具链.cmake
set(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /Wall /GR /EHsc" CACHE INTERNAL "")
Run Code Online (Sandbox Code Playgroud)
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"
}
]
}
Run Code Online (Sandbox Code Playgroud)
在 CMake 3.15 中,CMake 引入了针对此 MSVC 特定警告的修复:
cl : Command line warning D9025: overriding '/W3' with '/W4'
Run Code Online (Sandbox Code Playgroud)
/W3并且不再自动添加编译器警告标志(如)。因此,通过升级到 CMake 3.15 或更高版本,此警告不应再出现。来自文档:
在 CMake 3.14 及更低版本中使用类似 MSVC 的编译器时,默认情况下
/W3会添加类似警告标志CMAKE_<LANG>_FLAGS。对于想要以编程方式选择不同警告级别的项目来说,这是有问题的。特别是,它需要CMAKE_<LANG>_FLAGS在了解 CMake 内置默认值的情况下对变量进行字符串编辑,以便可以替换它们。
CMAKE_<LANG>_FLAGSCMake 3.15 及更高版本倾向于在默认值中省略警告标志。
除了此修复之外,CMake 还引入了策略CMP0092,该策略允许您在必要时切换回该OLD行为(默认添加警告标志)。
| 归档时间: |
|
| 查看次数: |
15211 次 |
| 最近记录: |