CMake 使用学习
1. 概述
CMake 工具能够自动生成 Makefile 文件,减轻手写 Makefile 文件的工作量,同时减少书写 Makefile 文件产生的错误。
2. CMake 命令
CMake 运行主要分为两个阶段:
- 
配置阶段:解析 CMakeLists.txt 文件 
- 
生成阶段:生成构建环境 
有关 cmake 的详细参数参见 cmake --help,本文仅对其中较难理解的选项加以描述。
2.1 缓存选项
CMake 支持缓存选项。在 CMake 中,如果一个变量被标记为「缓存」,则 cmake 的时候会将其写入到 CMakeCache.txt 文件中。当 cmake 命令寻找变量时,它会首先去 CMakeCache.txt 文件中寻找。cmake 创建缓存选项的格式如下:
| 1 | cmake -D <var>[:<type>]=<value> # <var>[:<type>]=<value> 具体参见下文「CMakeCache.txt 编写」 | 
2.2 常用选项
- 
-DCMAKE_BUILD_TYPE=:指定编译软件的版本格式,取值为Release、RelWithDebInfo、Debug等。
- 
-DCMAKE_INSTALL_PREFIX=:指定需要安装的软件路径,默认为安装路径为/usr/local(默认系统安装)。
仅用户安装一般指定安装路径为
~/.local,当然也可以随用户自定义。
- -DBUILD_SHARED_LIBS=:- DBUILD_SHARED_LIBS是一个全局的 flag,为- bool类型,取值为- ON或- OFF(默认为- ON)。其作用是:
如果
DBUILD_SHARED_LIBS设定为ON,则 CMakeLists.txt 中所有的add_library()创建的库都默认为共享库而不是静态库,除非add_library()中有显式地指定编译为静态库。反之则为静态库。
- -DBUILD_TESTING=:- DBUILD_TESTING是一个全局的 flag,为- bool类型,取值为- ON或- OFF(默认为- ON)。其作用是:
当使用 CTest 模块时,
DBUILD_TESTING用来控制是否使能 testing。
- --trace:用于详细输出- cmake的每一行信息。
--trace-source=<file>:将cmake输出的所有信息都保存在file文件中。
3. CMakeLists.txt 编写
3.1 设定编译器
在运行 CMake 前首先需要指定 CC、CXX 编译器,否则 CMake 将使用系统默认的 CC、CXX 编译器。可以在 bash shell 中临时设定:
| 1 | CC=/usr/bin/gcc | 
也可以在 CMakeLists.txt 文件中设定:
| 1 | set(CMAKE_C_COMPILER "/usr/bin/gcc") | 
3.2 添加 CMake 最小要求版本
| 1 | cmake_minimum_required(VERSION 3.1) | 
3.3 添加项目信息
| 1 | project(MyProject VERSION 1.0 # 项目版本 | 
CMake 支持的语言有:C , CXX , Fortran , ASM , CUDA (CMake 3.8+), CSharp (3.8+), and SWIFT (CMake 3.15+experimental)。默认为 C 和 CXX 。
3.4 生成文件
- 生成目标文件
| 1 | add_executable(one two.cpp three.h) | 
one 既是生成的可执行文件名称,也是 CMake 创建的目标文件的名称。one 后面紧跟着项目的源文件,比如这里示例的 two.cpp three.h 都是源文件。
- 生成库文件
| 1 | add_library(onelib STATIC twolib.cpp threelib.h) | 
可选的库文件类型有:STATIC、SHARED、MODULE 。
3.5 为目标文件添加内容
【注】可以为目标文件添加这些内容:
include directories, linked libraries (or linked targets), compile options, compile definitions, compile features, and more.
- 为目标文件添加 include 路径
| 1 | target_include_directories(one PUBLIC include) | 
PUBLIC/PRIVATE/INTERFACE 用来指定「是/否/仅需要时」影响其他依赖于当前目标文件 one 的目标文件。
- 为目标文件添加链接库
| 1 | target_link_libraries(one -lcrypt -lcap) | 
one 是 CMake 创建的目标文件的名称。
3.6 设定变量、缓存项、属性
【注】访问一个名为 VARIABLE 的局部变量使用 ${VARIABLE},访问一个名为 VARIABLE 的环境变量使用 $ENV{VARIABLE}。
- 设定局部变量
| 1 | set(MY_VARIABLE "value") | 
局部变量的值还可以是列表:
| 1 | set(MY_VARIABLE "one" "two") | 
上述两条语句等价,因为变量的列表值在内部存储时就是使用 “;” 分隔的。可以添加 PARENT_SCOPE 关键字指定将变量的作用域往外跳一级。
- 设定缓存变量
| 1 | set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "Description") # 不会覆盖已存在的变量 | 
- 修改命令行参数变量
| 1 | option(MY_OPTION "This is settable from the command line" OFF) # 此处假定 MY_OPTION 为 bool 值 | 
- 设定环境变量
| 1 | set(ENV{variable_name} value) | 
- 设定属性 & 访问属性
 属性可以看作是依附于某一项(比如目录、目标文件等)的全局变量。
| 1 | set_property(TARGET TargetName[TargetName1...] PROPERTY CXX_STANDARD 11) # 可以为多个 targets/files/tests 设置属性 | 
3.7 if 语句块
| 1 | 
 | 
if 语句块中可以包含的关键字有:
- 
一元:NOT、TARGET、EXISTS(file)、DEFINED 等 
- 
二元:STREQUAL、AND、OR、MATCHES(regular expression)、VERSION_LESS、VERSION_LESS_EQUAL 等 
- 
括号:() 
3.8 生成表达式
- 
$<KEYWORD>:计算 KEYWORD 的值
- 
$<KEYWORD:value>:根据 KEYWORD 的值来控制整个表达式的值,KEYWORD = 1 时表达式值为 value,KEYWORD = 0 时表达式值为空字符串。
常用的生成表达式有 BUILD_INTERFACE 和 INSTALL_INTERFACE 生成表达式。
| 1 | target_include_directories( | 
BUILD_INTERFACE 表达式包装的构建需求只被在同一个构建系统下,或者使用 export() 指令导出的目标上使用。INSTALL_INTERFACE 表达式包装的构建需求只被用在使用 install(EXPORT) 指令安装和导出的目标上:
3.9 函数和宏
函数和宏的唯一区别在于作用域,函数有作用域但宏没有。
| 1 | 
 | 
CMake 中有一个参数接收模块:cmake_parse_arguments(),用来定义函数/宏需要接收的参数。
| 1 | 
 | 
上文调用函数后可以发现:
| 1 | COMPLEX_PREFIX_SINGLE = TRUE | 
如果函数/宏调用时传入了 cmake_parse_arguments() 未指定的其他参数,则其内容均保存在 COMPLEX_PREFIX_UNPARSED_ARGUMENTS 变量中。
4. CMakeCache.txt 编写
CMakeCache.txt 文件本是由 cmake 命令默认生成的,但其内容是可以修改的。CMakeCache.txt 文件主要保存的是 cmake 过程中需要使用的环境变量,当 cmake 命令寻找变量时,它会首先去 CMakeCache.txt 文件中寻找。
4.1 内容条目
随便看一个 CMakeCache.txt 文件就会发现,其文首给出了该文件的作用和内容条目格式:
| 1 | # This is the CMakeCache file. | 
简单来说,CMakeCache.txt 文件就是一条条环境变量的键(包含类型)值对条目组成的,而条目的具体格式如下:
| 1 | KEY:TYPE=VALUE | 
5. 注释
在可编写的 CMake 文件(CMakeLists、CMakeCache.txt等)中,其注释规则都是一样的。
5.1 单行注释
| 1 | # 要注释的单行内容 | 
5.2 多行注释
| 1 | #[[ | 








