我想编写一个 cmake 文件,在调试和发布版本中为 clang++、g++ 和 MSVC 设置不同的编译器选项.我目前正在做的事情看起来像这样:
if(MSVC)设置(CMAKE_CXX_FLAGS${CMAKE_CXX_FLAGS}/std:c++latest/W4")# 默认调试标志没问题设置(CMAKE_CXX_FLAGS_RELEASE{CMAKE_CXX_FLAGS_RELEASE}/O2")别的()设置(CMAKE_CXX_FLAGS${CMAKE_CXX_FLAGS} -std=c++1z -Wall -Wextra -Werror")设置(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} 一些其他标志")设置(CMAKE_CXX_FLAGS_RELEASE${CMAKE_CXX_FLAGS_RELEASE} -O3")if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")设置(CMAKE_CXX_FLAGS${CMAKE_CXX_FLAGS} -stdlib=libc++")别的()# 目前对 gcc 没有什么特别的万一()万一()
但是我有几个问题:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} Foo")
替换为 append(CMAKE_CXX_FLAGS "Foo")代码>?
CMAKE_CXX_FLAGS
和类似的变量,但我不确定要使用什么其他机制.make foo_debug_clang
.所以我的问题是
我在互联网上找到的大多数参考资料要么过时,要么只展示了一些琐碎的例子.我目前使用 cmake3.8,但如果这有什么不同,我对更新版本的答案更感兴趣.
您的方法 - 正如@Tsyvarev 所评论的那样 - 绝对没问题,因为您在 CMake 中要求新"方法,这就是您的代码将转化为:
cmake_minimum_required(VERSION 3.8)项目(你好世界)细绳(APPEND _opts"$,""/W4;$<$:/O2>,"-Wall;-Wextra;-Werror;"$<$:-O3>""$<$<CXX_COMPILER_ID:Clang>:-stdlib=libc++>">")add_compile_options("${_opts}")add_executable(HelloWorld "main.cpp")target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)
<小时>
您使用
CMakeSettings.json
<代码>{//有关此文件的更多信息,请参阅 https://go.microsoft.com//fwlink//?linkid=834763.配置":[{"name": "x86-调试","generator": "Visual Studio 15 2017","configurationType": "调试","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}","buildCommandArgs": "-m -v:minimal",},{"name": "x86-Release","generator": "Visual Studio 15 2017","configurationType": "发布","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}","buildCommandArgs": "-m -v:minimal",},{"name": "Clang-调试","generator": "Visual Studio 15 2017","configurationType": "调试","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}","cmakeCommandArgs": "-T"LLVM-vs2014"","buildCommandArgs": "-m -v:minimal",},{"name": "Clang-Release","generator": "Visual Studio 15 2017","configurationType": "发布","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}","cmakeCommandArgs": "-T"LLVM-vs2014"","buildCommandArgs": "-m -v:minimal",},{"name": "GNU 调试","generator": "MinGW Makefiles","configurationType": "调试","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",变量":[{"name": "CMAKE_MAKE_PROGRAM","value": "${projectDir}\mingw32-make.cmd"}]},{"name": "GNU 版本","generator": "Unix Makefiles","configurationType": "发布","buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",变量":[{"name": "CMAKE_MAKE_PROGRAM","value": "${projectDir}\mingw32-make.cmd"}]}]}
mingw32-make.cmd
@echo offmingw32-make.exe %~1 %~2 %~3 %~4
因此,您可以在 Visual Studio 2017 中使用任何 CMake 生成器,但有一些不健康的引用(如 2017 年 9 月,可能稍后修复)需要 mingw32-make.cmd
中介器(删除引号).
I want to write a cmake file that sets different compiler options for clang++, g++ and MSVC in debug and release builds. What I'm doing currently looks something like this:
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /W4")
# Default debug flags are OK
set(CMAKE_CXX_FLAGS_RELEASE "{CMAKE_CXX_FLAGS_RELEASE} /O2")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z -Wall -Wextra -Werror")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} some other flags")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
else()
# nothing special for gcc at the moment
endif()
endif()
But I have a couple of problems with this:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} Foo")
with append(CMAKE_CXX_FLAGS "Foo")
? CMAKE_CXX_FLAGS
and similar variables in the first place, but im not sure what other mechanism to use.make foo_debug_clang
.So my questions are
Most references I could find on the internet are either out of date or show only trivial examples. I currently using cmake3.8, but if that makes any difference, I'm even more interested in the answer for more recent versions.
Your approach would - as @Tsyvarev has commented - be absolutely fine, just since you've asked for the "new" approach in CMake here is what your code would translate to:
cmake_minimum_required(VERSION 3.8)
project(HelloWorld)
string(
APPEND _opts
"$<IF:$<CXX_COMPILER_ID:MSVC>,"
"/W4;$<$<CONFIG:RELEASE>:/O2>,"
"-Wall;-Wextra;-Werror;"
"$<$<CONFIG:RELEASE>:-O3>"
"$<$<CXX_COMPILER_ID:Clang>:-stdlib=libc++>"
">"
)
add_compile_options("${_opts}")
add_executable(HelloWorld "main.cpp")
target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)
You take add_compile_options()
and - as @Al.G. has commented - "use the dirty generator expressions".
There are some downsides of generator expressions:
$<IF:...,...,...>
expression is only available in CMake version >= 3.8string(APPEND ...)
, which you can also use to "optimize" your set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...
calls.So better use a more readable and backward compatible approach with add_compile_options()
:
if(MSVC)
add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
else()
add_compile_options("-Wall" "-Wextra" "-Werror" "$<$<CONFIG:RELEASE>:-O3>")
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options("-stdlib=libc++")
else()
# nothing special for gcc at the moment
endif()
endif()
And yes, you don't explicitly specify the C++ standard anymore, you just name the C++ feature your code/target does depend on with target_compile_features()
calls.
For this example I've chosen cxx_lambda_init_captures
which would for e.g. an older GCC compiler give the following error (as an example what happens if a compiler does not support this feature):
The compiler feature "cxx_lambda_init_captures" is not known to CXX compiler
"GNU"
version 4.8.4.
And you need to write a wrapper script to build multiple configurations with a "single configuration" makefile generator or use a "multi configuration" IDE as Visual Studio.
Here are the references to examples:
So I've tested the following with the Open Folder
Visual Studio 2017 CMake support to combine in this example the cl, clang and mingw compilers:
CMakeSettings.json
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "x86-Release",
"generator": "Visual Studio 15 2017",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "Clang-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"cmakeCommandArgs": "-T"LLVM-vs2014"",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "Clang-Release",
"generator": "Visual Studio 15 2017",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"cmakeCommandArgs": "-T"LLVM-vs2014"",
"buildCommandArgs": "-m -v:minimal",
},
{
"name": "GNU-Debug",
"generator": "MinGW Makefiles",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"variables": [
{
"name": "CMAKE_MAKE_PROGRAM",
"value": "${projectDir}\mingw32-make.cmd"
}
]
},
{
"name": "GNU-Release",
"generator": "Unix Makefiles",
"configurationType": "Release",
"buildRoot": "${env.LOCALAPPDATA}\CMakeBuild\${workspaceHash}\build\${name}",
"variables": [
{
"name": "CMAKE_MAKE_PROGRAM",
"value": "${projectDir}\mingw32-make.cmd"
}
]
}
]
}
mingw32-make.cmd
@echo off
mingw32-make.exe %~1 %~2 %~3 %~4
So you can use any CMake generator from within Visual Studio 2017, there is some unhealthy quoting going on (as for September 2017, maybe fixed later) that requires that mingw32-make.cmd
intermediator (removing the quotes).
这篇关于在跨平台 cmake 项目中设置编译器标志的现代方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!