Cmake学习
CMake是一个开源的、跨平台的自动化构建工具,通过cmake我们可以轻松地管理我们的项目。
注意:
CMake并不是包管理工具!
CMake并不只支持C/C++!
掌握CMake是学习C++必经之路!
CMake与Makefile、Make的关系
Makefile并不跨平台,CMake会根据编译器的类型来决定是否生成Makefile,大多数情况下CMake会生成Makefile
大型项目不推荐大家手动编写Makefile
Make工具(类似批处理工具)是通过调用makefile文件中的命令实现编译和链接的
CMake流程图

CMake 命令行执行流程
1.编写CMakeLists.txt文件,下面是最基本的配置
- cmake_minimum required(VERSION 3.20)#最小版本。
- project(Hello)#项目名
- add_executable(Hello hello.cpp)#由源文件生成一个可执行的程序。
2.cmake -B build
- 创建一个build并在此目录下生成makefile或其他文件。
3.cmake –build build
- 生成项目。
CMake Language概述
CMake项目是基于CMakeLists.txt构建的,在CMakeLists.txt中(或是*.cmake)我们用到的就是CMake Language
CMake Language的语法非常像一些命令式编程语言
执行从源树(CMakeLists.txt)的根文件文件开始
cmake命令行工具是由五个可执行文件构成
- cmake
- ctest
- cpack
- cmake-gui
- ccmake
如何不通过CMakeLists.txt,运行CMake
cmake -P *.cmake
以上用法很少在项目中用到,但适合学习CMake语法

变量操作 set、list
CMake中的变量分为两种
- CMake提供
- 自定义
CMake变量的命名区分大小写
CMake中的变量在存储时都是字符串
CMake获取变量:${变量名}
变量的基础操作是set()与unset(),但你也可以用list或是string操作变量
Set
set(
… [PARENT SCOPE]) set可以给一个变量设置多个值
变量内部存储时使用”:”分割,但显示时只进行连接处理
List
list(APPEND
- [
..])列表添加元素 list(REMOVEITEM
[value..]) 列表删除元素 list(LENGTH
list(FIND
)在列表中查找元素返回索引 list(INSERT
[ …])在index位置插入 list(REVERSE
- )反转list
list(SORT
- […])排序list
流程控制
if条件流程控制
loop 循环流程控制
- break
- continue
1 | |
函数
- 定义函数的语法
function([ …])
endfunction()
1 | |
Scope作用域
CMake 有两种作用域
1.Function scope 函数作用域
2.Directory scope 当从add subdirectory()命令执行嵌套目录中的CMakeLists.txt列表文件
时,注意父CMakeLists.txt其中的变量可以被子CMakeLists.txt使用
CMake 构建项目的四种方式
直接写入源码路径的方式
- add executable中直接写入相对路径
- 在源码中引入头文件时需要写相对路径
调用子目录cmake脚本的方法
- include方法可以引入子目录中的cmake后缀的配置文件
- 将配置加入add executable中
CMakeLists嵌套(最常见)
- target include_directories 头文件目录的声明
- target link libraries 连接库文件
- add subdirectory 添加子目录
- add library 生成库文件
- 默认 STATIC library
Object Libraries
- add library OBJECT
- Object Library 是一个特殊的库类型,它将目标文件编译成一个库,但不会生成最终的链接文件。这意味着你可以在后续的 add library()或 add executable()命令中,将 Object Library 作为源文件进行链接,从而生成最终的可执行文件或库文件。
- 将target include directories移入到子CMakeLists中
- add library OBJECT
CMake 如何生成动态库/静态库
- 静态库
- 在连接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态连接。对函数库的连接是在编译时完成的!
- 动态库
- 动态库不是在编译时被连接到目标代码中,而是运行时是才被载入.
- 静态库对空间的浪费是巨大的!
动态库的命名
lib<name>.so/dll
静态库的命名
lib<name>.a/lib
命令
- file()常用于搜索源文件
- add_library(animal STATIC ${SRC})生成静态库
- add_library(animal SHARED ${SRC})生成动态库
- ${LIBRARY_OUTPUT_PATH}导出目录