C++ 默认在 CMake 中优化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41361631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Optimize in CMake by default
提问by marmistrz
I have a C++ project which uses CMake as its build system. I'd like the following behavior:
我有一个 C++ 项目,它使用 CMake 作为其构建系统。我想要以下行为:
If cmake is invoked as cmake ..
, then CMAKE_CXX_FLAGS
is -O3 -Wall -Wextra
如果 cmake 被调用为cmake ..
,则CMAKE_CXX_FLAGS
是-O3 -Wall -Wextra
If cmake is invoked as cmake .. -DCMAKE_BUILD_TYPE=Debug
, then CMAKE_CXX_FLAGS
is -g -Wall -Wextra
如果 cmake 被调用为cmake .. -DCMAKE_BUILD_TYPE=Debug
,则CMAKE_CXX_FLAGS
是-g -Wall -Wextra
I tried the following
我尝试了以下
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")
But this has a big problem. First of all, if the second invocation is used, then both -O3
and -g
flags are passed to the compiler. Besides, if I use the second invocation and the first thereafter, CMAKE_BUILD_TYPE
stays Debug
although not explicitly ordered so - so I get a Debug build although I want an optimized build.
但这有一个很大的问题。首先,如果使用第二次调用,则-O3
和-g
标志都将传递给编译器。此外,如果我使用第二次调用和此后的第一次调用,尽管没有明确排序,但CMAKE_BUILD_TYPE
仍然保持不变Debug
- 所以尽管我想要一个优化的构建,但我得到了一个调试构建。
Why? What can I do to get the desired behavior?
为什么?我该怎么做才能获得所需的行为?
回答by Angew is no longer proud of SO
First off: recommended usage of CMake is to always specify CMAKE_BUILD_TYPE
explicitly on the command line (if and only if using a single-configuration generator). Your use case deviates from this best practice, so treat this answer as "how you can do it," not necessarily as "how you should do it."
首先:推荐的 CMake 用法是始终CMAKE_BUILD_TYPE
在命令行上明确指定(当且仅当使用单配置生成器时)。您的用例偏离了此最佳实践,因此将此答案视为“您可以如何做”,而不一定是“您应该如何做”。
To address the first issue, you should be able to do this early in your CMakeList:
要解决第一个问题,您应该能够在 CMakeList 的早期执行此操作:
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
This will make sure that if you do not specify a build type at all, it will default to "Release" and thus CMAKE_CXX_FLAGS_RELEASE
will be used.
这将确保如果您根本不指定构建类型,它将默认为“发布”并因此CMAKE_CXX_FLAGS_RELEASE
将被使用。
The second one is harder to tackle. Variables passed from the command line (such as CMAKE_BUILD_TYPE=Debug
) are cachedby CMake and thus re-used in subsequent invocations (that is necessary, since CMake can re-trigger itself if you modify its inputs between builds).
第二个更难解决。从命令行传递的变量(例如CMAKE_BUILD_TYPE=Debug
)由 CMake缓存,因此在后续调用中重新使用(这是必要的,因为如果您在构建之间修改其输入,CMake 可以重新触发自身)。
The only solution is to make the user switch the build type explicitly again, using cmake .. -DCMAKE_BUILD_TYPE=Release
.
唯一的解决方案是让用户再次显式切换构建类型,使用cmake .. -DCMAKE_BUILD_TYPE=Release
.
Consider why this is necessary: as I said, CMake can re-trigger itself as part of a build if CMake's input (CMakeLists.txt
files or their dependencies) has changed since last CMake ran. In such case, it will also be run without command-line arguments such as -DCMAKE_BUILD_TYPE=whatever
, and will rely on the cache to supply the same value as last time. This scenario is indistinguishable from you manually running cmake ..
without additional arguments.
考虑为什么这是必要的:正如我所说,如果 CMake 的输入(CMakeLists.txt
文件或其依赖项)自上次 CMake 运行以来发生了变化,CMake 可以重新触发自身作为构建的一部分。在这种情况下,它也将在没有命令行参数的情况下运行,例如-DCMAKE_BUILD_TYPE=whatever
, 并将依赖缓存提供与上次相同的值。这种情况与您在cmake ..
没有其他参数的情况下手动运行没有区别。
I could provide a hacky solution to always reset CMAKE_BUILD_TYPE
to Release
if not specified explicitly on the command line. However, it would also mean that a buildsystem generated as Debug
would get re-generated as Release
if automatic re-generation happened. I am pretty sure that's not what you want.
如果未在命令行中明确指定,我可以提供一个 hacky 解决方案,以始终重置CMAKE_BUILD_TYPE
为Release
。但是,这也意味着生成的构建系统Debug
会重新生成,Release
就像自动重新生成发生一样。我很确定这不是你想要的。
回答by roalz
For CXX flags specific for Release target, you should set
CMAKE_CXX_FLAGS_RELEASE
instead of
CMAKE_CXX_FLAGS
对于特定于发布目标的 CXX 标志,您应该设置
CMAKE_CXX_FLAGS_RELEASE
而不是
CMAKE_CXX_FLAGS
In your case you can use:
在您的情况下,您可以使用:
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
设置(CMAKE_CXX_FLAGS“-Wall -Wextra”)
设置(CMAKE_CXX_FLAGS_DEBUG“-g”)
设置(CMAKE_CXX_FLAGS_RELEASE“-O3”)
A more modern CMake approach (which I suggest, if you are using CMake version 2.8.12 or newer), is well described in this StackOverflow answerand involves the use of target_compile_options.
更现代的 CMake 方法(我建议,如果您使用的是 2.8.12 或更高版本的 CMake),在这个 StackOverflow 答案中有很好的描述,并且涉及到target_compile_options的使用。
回答by Mike T
The default optimization level for various release modes is O3, which often isn't the best choice. Within CMakeLists.txt
file, these can be modified to O2:
各种发布模式的默认优化级别是 O3,这通常不是最佳选择。在CMakeLists.txt
文件中,这些可以修改为 O2:
# Modify compile flags to change optimization level from O3 to O2
string(REGEX REPLACE "([\/\-]O)3" "\12"
CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REGEX REPLACE "([\/\-]O)3" "\12"
CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
string(REGEX REPLACE "([\/\-]O)3" "\12"
CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
string(REGEX REPLACE "([\/\-]O)3" "\12"
CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
These regular expressions will be modified (e.g.):
这些正则表达式将被修改(例如):
-O3
to-O2
usually for Linux-based compilers/O3
to/O2
usually for Windows-based compilers
-O3
以-O2
通常基于Linux编译器/O3
以/O2
通常为基于Windows的编译器