默认情况下在CMake中进行优化

mar*_*trz 23 c++ cmake compiler-optimization

我有一个C++项目,它使用CMake作为它的构建系统.我想要以下行为:

如果调用cmake cmake ..,CMAKE_CXX_FLAGS则为-O3 -Wall -Wextra

如果调用cmake cmake .. -DCMAKE_BUILD_TYPE=Debug,CMAKE_CXX_FLAGS则为-g -Wall -Wextra

我尝试了以下内容

message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

set(CMAKE_CXX_FLAGS "-O3 -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")
Run Code Online (Sandbox Code Playgroud)

但这有一个很大的问题.首先,如果使用第二次调用,则将两者-O3-g标志传递给编译器.此外,如果我使用第二次调用和之后的第一次调用,虽然没有明确排序,但CMAKE_BUILD_TYPE仍然保留Debug- 所以我得到一个Debug构建,尽管我想要一个优化的构建.

为什么?我该怎么做才能获得理想的行为?

Rei*_*ica 45

首先:建议使用CMake始终CMAKE_BUILD_TYPE在命令行上明确指定(当且仅当使用单配置生成器时).您的用例偏离了这种最佳做法,因此将此答案视为"您如何做到",而不一定是"您应该如何做".

要解决第一个问题,您应该可以在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")
Run Code Online (Sandbox Code Playgroud)

这将确保如果您根本没有指定构建类型,它将默认为"Release",因此CMAKE_CXX_FLAGS_RELEASE将被使用.

第二个更难解决.从命令行传递的变量(例如CMAKE_BUILD_TYPE=Debug)由CMake 缓存,因此在后续调用中重复使用(这是必要的,因为如果在构建之间修改其输入,CMake可以重新触发自身).

唯一的解决方案是使用户再次显式地切换构建类型cmake .. -DCMAKE_BUILD_TYPE=Release.

考虑为什么这是必要的:正如我所说的,如果CMake的输入(CMakeLists.txt文件或它们的依赖关系)自上次CMake运行以来发生了变化,CMake可以重新触发自身作为构建的一部分.在这种情况下,它也将在没有命令行参数的情况下运行-DCMAKE_BUILD_TYPE=whatever,并且将依赖缓存来提供与上次相同的值.此方案与您在cmake ..没有其他参数的情况下手动运行无法区分.

我可以提供一个hacky解决方案,如果未在命令行中明确指定CMAKE_BUILD_TYPE,Release则始终重置为.但是,这也意味着生成的构建系统Debug会重新生成,就Release好像自动重新生成一样.我很确定这不是你想要的.


roa*_*alz 8

对于特定于Release目标的CXX标志,您应该设置
CMAKE_CXX_FLAGS_RELEASE
而不是
CMAKE_CXX_FLAGS

在您的情况下,您可以使用:

set(CMAKE_CXX_FLAGS"-Wall -Wextra")
设置(CMAKE_CXX_FLAGS_DEBUG"-g")
设置(CMAKE_CXX_FLAGS_RELEASE"-O3")

更现代的CMake方法(我建议,如果您使用的是CMake版本2.8.12或更新版本),在此StackOverflow答案中有详细描述,并涉及使用target_compile_options.