以下内容为自己的学习笔记,如需求转载,请声明原文链接 微信大众号「ENG八戒」mp.weixin.qq.com/s/CsvCzH6r8…

工程实践:CMake 编译类型的装备

程序在正常情况下的工作,咱们都期望它跑得又稳又快,资源又不占用太多,文件大小还不占空间,在开发者看来,这归于发布版别,编译输出时应该是 Release 形式。

相反,在软件开发进程中,大多数时候编译类型都是默许调试(Debug)形式,由于 Debug 形式可以输出很多便利调试的信息,在 linux 系统下乃至允许发生 core-dump 文件,帮助还原崩溃现场的堆栈信息,但对运转速度却没有过多要求。

那么为什么编译类型不同会对履行程序的运用发生不一样的才能呢?

其实说白了,编译类型对履行程序的影响是通过编译器在编译时对软件功用的开关效果和代码结构的转化等。不同编译参数和选项,开关不同的功用,比方调试信息的输出,以及对应不同的代码优化策略

冗余的删除,比方死代码删除,常量或许复写传达,公共子表达式删除等等。

核算强度削弱,包括但不仅限于一些根据逻辑或许算术表达式的优化,例如把乘法转化成一系列的位移和加减法的组合,常量核算进程转换成结果等。

扩展优化器的效果范围的优化,例如内联,基本块兼并等等,基本意图在于获得更大的优化目标

系统相关的优化,简单如指令选择时的一些窥孔性质的指令兼并,复杂如寄存器分配,指令调度等np问题的解决。

以 C/C++ 流行的构建系统 cmake 为例,cmake 会根据预界说的编译类型给编译器输入指定的参数和标志位,也便是说编译类型对于 cmake 来说就是枚举类型,可是每个类型分别对应着不同的编译参数和标志。既然如此,编译类型其实也可以自界说,由于终究关心的是给编译器输入什么详细参数。

那么除了 debug 形式,cmake 供给了哪几种预界说的可装备编译类型呢?

CMAKE_BUILD_TYPE 说明
Debug 调试版别,没有优化,敞开断语,最全调试信息
Release 正式版别,最高优化,没有调试信息,封闭断语
MinSizeRel 体积较小的版别,但速度没有优化
RelWithDebInfo 优化,保留了调试信息,封闭断语

上面的这些预界说的编译类型又是怎么控制传递给编译器的参数和标志位呢?

Cmake 供给了两组很直观的参数变量:

CMAKE_<LANG>_FLAGS
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_<LANG>_FLAGS_<CONFIG>
CMAKE_C_FLAGS_DEBUG
CMAKE_CXX_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELWITHDEBINFO

CMAKE_<LANG>_FLAGS 变量组存储的是针对特定言语的编译参数和选项。编译代码的时候,编译器输入的参数会包括这组参数变量中对应变量的内容。

比方,编译 C 言语代码,会传输 CMAKE_C_FLAGS 的内容给到编译器;编译 C++ 言语代码,会传输 CMAKE_CXX_FLAGS 的内容给到编译器。

一般,CMAKE_<LANG>_FLAGS_<CONFIG> 变量组会包括特定言语特定形式的对应编译参数和选项。编译代码的时候,编译器输入的参数会按照编译类型来决议包括这组参数变量中对应变量的内容。

比方,编译 C 言语代码,假如选择 Debug 形式,会输入 CMAKE_C_FLAGS_DEBUG 的内容给到编译器;假如选择 Release 形式,会输入 CMAKE_C_FLAGS_RELEASE 的内容给到编译器,以此类推。

装备方法

1. 装备 CMAKE_<LANG>_FLAGS

假如是直接装备 CMAKE_<LANG>_FLAGS 的值,则可以疏忽 CMAKE_BUILD_TYPE 的值。<LANG> 代指各种编程言语,比方 C、CXX

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -lm -lrt -Os -g -rdynamic -funwind-tables -ffunction-sections")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lm -lrt -Os -g -rdynamic -funwind-tables -ffunction-sections")
SET(LIBRARY_OUTPUT_PATH "./../../src/libs")

但一般写法是利用 CMAKE_BUILD_TYPE 的值作为条件变量,用于判断选择装备 CMAKE_<LANG>_FLAGS 的值

IF (CMAKE_BUILD_TYPE STREQUAL Debug)
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -lm -lrt -Os -g -rdynamic -funwind-tables -ffunction-sections -Wall -Werror")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lm -lrt -Os -g -rdynamic -funwind-tables -ffunction-sections -Wall -Werror")
ELSEIF (CMAKE_BUILD_TYPE STREQUAL Release)
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -lm -lrt -Os -s -ffunction-sections -Wall")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lm -lrt -Os -s -ffunction-sections -Wall -Werror")
ELSE ()
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -lm -lrt -Os -s")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -lm -lrt -Os -s")
ENDIF()

2. 装备 CMAKE_<LANG>_FLAGS_<CONFIG>

装备一切 CMAKE_<LANG>_FLAGS_<CONFIG> 的值,CMake 主动根据 CMAKE_BUILD_TYPE 的值选择将哪个 CMAKE_<LANG>_FLAGS_<CONFIG> 值传递给编译器

# SET(CMAKE_BUILD_TYPE Debug)
SET(CMAKE_BUILD_TYPE Release)
SET(FLAGS_C "-pthread -lm -lrt")
SET(FLAGS_CXX "-pthread -lm -lrt")
SET(FLAGS_DEBUG "-g -rdynamic -funwind-tables -ffunction-sections -Wall -ggdb")
#SET(FLAGS_RELEASE "-O3 -s -DNDEBUG -DLINUX -fshort-enums -lmsmart")
SET(FLAGS_RELEASE "-pthread -lm -lrt -Os -s -fPIC -O2 -g -DLINUX -Wall -Werror")
SET(FLAGS_MINSIZEREL "-Os -s -DNDEBUG")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} ${FLAGS_C} ${FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS} ${FLAGS_CXX} ${FLAGS_DEBUG}")
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} ${FLAGS_C} ${FLAGS_RELEASE}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS} ${FLAGS_CXX} ${FLAGS_RELEASE}")
SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS} ${FLAGS_C} ${FLAGS_MINSIZEREL}")
SET(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS} ${FLAGS_CXX} ${FLAGS_MINSIZEREL}")

从姓名来看,cmake 的自带变量都是以 CMAKE 最初。FLAGS_C、FLAGS_CXX、FLAGS_DEBUG、FLAGS_RELEASE、FLAGS_MINSIZEREL 都是自界说变量,存储了某些参数选项,便利重复运用。

CMAKE_BUILD_TYPE CMAKE_<LANG>_FLAGS_<CONFIG>
Debug CMAKE_C_FLAGS_DEBUG
CMAKE_CXX_FLAGS_DEBUG
Release CMAKE_C_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELEASE
MinSizeRel CMAKE_C_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_MINSIZEREL
RelWithDebInfo CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELWITHDEBINFO