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

Optimize in CMake by default

本文关键字:优化 CMAKE 情况下 默认      更新时间:2023-10-16

我有一个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")

但这有一个大问题。首先,如果使用了第二个调用,则-O3-g标志都传递给编译器。此外,如果我使用第二个调用,此后第一次调用,则CMAKE_BUILD_TYPE仍保持Debug,尽管没有明确订购,所以我得到了调试构建,尽管我想要优化的构建。

为什么?我该怎么做才能获得所需的行为?

首先:建议使用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")

这将确保如果您根本不指定构建类型,则将默认为"发布",因此将使用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 ..的情况是无法区分的。

我可以提供一个骇客解决方案,以始终将CMAKE_BUILD_TYPE重置为Release,如果未在命令行上明确指定。但是,这也意味着如果发生自动重新生成,则为Debug生成的构建系统将被重新生成为 Release 。我很确定那不是您想要的。

对于特定于发行目标的CXX标志,您应该设置
cmake_cxx_flags_release
而不是
cmake_cxx_flags

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

set(cmake_cxx_flags" -wall -wextra")
set(cmake_cxx_flags_debug" -g")
set(cmake_cxx_flags_release" -o3")

在此stackoverflow答案中很好地描述了一种更现代的CMAKE方法(我建议您使用CMAKE版本2.8.12或更新),并涉及target_compile_options的使用。

各种发行模式的默认优化级别是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}")

这些正则表达式将进行修改(例如):

  • -O3-O2通常用于基于Linux的编译器
  • /O3/O2通常用于基于Windows的编译器