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

时间:2016-12-28 11:56:17

标签: c++ cmake compiler-optimization

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

如果以cmake ..方式调用cmake,则CMAKE_CXX_FLAGS-O3 -Wall -Wextra

如果以cmake .. -DCMAKE_BUILD_TYPE=Debug方式调用cmake,则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,尽管没有明确排序,所以我得到了一个Debug构建,尽管我想要一个优化的构建。

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

3 个答案:

答案 0 :(得分:40)

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

这将确保如果您根本没有指定构建类型,它将默认为" 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 。我很确定这不是你想要的。

答案 1 :(得分:8)

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

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

  

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

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

答案 2 :(得分:0)

各种发行模式的默认优化级别是O3,often isn't the best choice。在import React, { Fragment, useContext } from 'react'; import ShoppingCart from '../components/ShoppingCart'; import { CartContext } from '../contexts/CartContext'; const cart = () => { const { cart } = useContext(CartContext); return ( <Fragment> {cart.length !== 0 ? ( <ShoppingCart /> ) : ( <div> <h1>Your cart is empty</h1> </div> )} </Fragment> ); }; export default cart; 文件中,可以将其修改为O2:

CMakeLists.txt

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

  • # 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,通常用于基于Linux的编译器
  • -O2/O3通常用于基于Windows的编译器