# cmake-tutorial
**Repository Path**: demon0511/cmake-tutorial
## Basic Information
- **Project Name**: cmake-tutorial
- **Description**: CMake学习^^
- **Primary Language**: C++
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-07-08
- **Last Updated**: 2023-07-09
## Categories & Tags
**Categories**: Uncategorized
**Tags**: cmake, Cpp
## README
# CMake学习
[TOC]
# 0 准备
## 0.1 实验环境
- 主机:Windows
- 命令行:WSL(Windows Subsystem for Linux), Ubuntu-20.04
- 依赖:Cmake3.20.0(构建工具),gcc9.4.0(编译工具)
```bash
# Cmake3.20.0 (Unbuntu22版本会自动安装最新版,但20版本需要手动安装)
cd $HOME
sudo apt update
sudo apt install -y libssl-dev
wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-x86_64.tar.gz
tar -xzvf cmake-3.20.0-linux-x86_64.tar.gz
echo 'export PATH="$HOME/cmake-3.20.0-linux-x86_64/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
cmake --version
# gcc
sudo apt-get install gcc
```
## 0.2 教程链接
[CMake实践应用专题 - 知乎 (zhihu.com)](https://www.zhihu.com/column/c_1369781372333240320)
[CMake 良心教程,教你从入门到入魂 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/500002865)
# 1 CMake构建
> [CMake应用:基础篇 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/367808125)
>
> [CMake 良心教程,教你从入门到入魂 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/500002865)
>
> [冷风 - 知乎 (zhihu.com)](https://www.zhihu.com/people/sprout37/posts)
## 1.1 CMake/Makefile/gcc的关系
- gcc(GNU Compiler Collection)将源文件编译(Compile)成可执行文件或者库文件
- 当需要编译的东西很多时,需要说明先编译什么,后编译什么,这个过程称为构建(Build)。常用的工具是make,对应的定义构建过程的文件为`Makefile`
- 由于编写Makefile对于大型项目又比较复杂,通过CMake就可以使用更加简洁的语法定义构建的流程,CMake定义构建过程的文件为`CMakeLists.txt`
## 1.2 cmake命令
- CMake提供cmake、ctest和cpack三个命令行工具分别负责构建、测试和打包。本文只介绍cmake命令,通过`cmake --help`可以看到cmake命令的使用方法,以下列举常见使用方法和可选参数:
- Usage(3种方法)
```bash
cmake [options]
cmake [options]
cmake [options] -S -B
```
- Specify a source directory to (re-)generate a build system for it in the current working directory.
- Specify an existing build directory to re-generate its build system.
- Options
| 参数 | 含义 |
| ------------------------------- | -------------------------------------------------------- |
| -S \ | 指定源文件根目录,必须包含一个CMakeLists.txt文件 |
| -B \ | 指定构建目录,构建生成的中间文件和目标文件的生成路径 |
| -D \[:\]=\ | 指定变量, -D后面的空格可以省略 |
| -G \ | 指定编译器,系统所有可用编译器在`cmake --help`的末尾显式 |
| --build \ | 执行构建,Build a CMake-generated project binary tree. |
## 1.3 CMake使用流程
1. 生成构建系统(buildsystem,比如make工具对应的Makefile)
```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DAUTHOR=RealCoolEngineer
```
- `-S .`:指明使用当前目录`.`作为源文件目录,其中包含`CMakeLists.txt`文件
- `-B build`:使用`build`目录作为构建目录,执行完成后,在项目的根目录下会创建build目录,其中生成了`Makefile`文件。这里创建了一个 build 目录存放编译产物,可以避免编译产物与代码文件混在一起,这种叫做外部构建;还有一种内部构建,即直接在项目根目录下进行构建系统与编译,会使得项目文件很混乱,一般直接用外部构建即可。
- 设定变量`CMAKE_BUILD_TYPE`的值为`Debug`,变量`AUTHOR`的值为`RealCoolEngineer`
2. 执行构建(比如make),生成目标文件
- 可以直接使用cmake命令:
```bash
cmake --build build
```
- 也可以使用等价的make命令:
```bash
cd build && make && cd ..
```
3. 执行测试、安装或打包
## 1.4 build目录介绍
- build 目录用来存放 cmake 构建和编译的产物,大致如下
```txt
build/
CMakeFiles/
lib/ 如果有库就会生成
cmake_install.cmake
CMakeCache.txt
demo 即CMakeLists.txt中设置的project名称
config.h 即CMakeLists.txt中设置的configure_file名称
Makefile
```
- 其中
- `lib/`文件夹存放库文件
- `CMakeCache.txt` 文件缓存变量
- `demo`是生成的执行文件,通过该文件运行程序
- `config.h` 是用于配置信息的头文件,是 cmake 根据 `config.h.in` 文件自动生成的。
- `Makefile` 是 cmake 根据顶级 CMakeLists.txt 生成的构建文件,通过该文件可以对整个项目进行编译。
- 由于CMake会缓存信息,因此重复运行`cmake -B build` 时就可以直接用缓存的值,就不需要重新检测编译器、检测编译特性是否支持C++17等信息。但有时候外部的情况有所更新(比如编译器卸载了,CMake却还是指向原来的地址),这时候 CMake 里缓存的却是旧的值,会导致一系列问题。
- 最简单的方法就是删除build文件夹然后重新`cmake -B build`
- Linux:rm -rf build
- Windows:rd /s /q build
- 删 build 虽然彻底,也会导致编译的中间结果(`.o`文件)都没了,重新编译要花费很长时间。如果只想清除缓存,不想从头重新编译,可以只删除 `CMakeCache.txt` 这个文件,因为它里面装的就是缓存的变量,删了他就可以让 CMake 强制重新检测一遍所有库和编译器。
- p.s. 90%的CMake错误都是缓存未更新导致的!
## 1.5 编码1:构建最小项目
- 项目结构
```txt
|_ cmake-tutorial/
|_ 1/
CMakeLists.txt
main.cpp
...
```
- main.cpp
```cpp
#include
int main() {
std::cout << "Hello CMake!" << std::endl;
return 0;
}
```
- CmakeList.txt
```cmake
cmake_minimum_required(VERSION 3.20)
# set the project name
project(demo)
# add the executable
add_executable(demo main.cpp)
```
- 构建与执行
```bash
cd 1 && cmake -B build && cmake --build build && build/demo && cd ..
```
# 2 CMake语法
> [CMake应用:核心语法篇 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/368701263)
>
> [CMake 良心教程,教你从入门到入魂 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/500002865)
>
> [CMake 入门实战 | HaHack](https://www.hahack.com/codes/cmake/)
## 2.1 CMake命令类型
CMake语言有3种命令类型:
1. 脚本命令([Scripting Commands](https://cmake.org/cmake/help/v3.21/manual/cmake-commands.7.html#id3)):always available.
- 例如`if`、`else`等命令
2. 项目配置命令([Project Commands](https://cmake.org/cmake/help/v3.21/manual/cmake-commands.7.html#id4)):available only in CMake projects.
- 例如`add_executable`、`include_directories `、`set_target_properties `等命令
3. 测试命令([CTest Commands](https://cmake.org/cmake/help/v3.21/manual/cmake-commands.7.html#id5)):available only in CTest scripts.
- 都是`ctest_`开头的命令
## 2.2 CMake文件类型
CMake语言在项目配置中组织为3种源文件类型:
1. 目录:`CMakeLists.txt`,针对的是一个目录,描述如何针对目录(Source tree)生成构建系统,会用到项目配置命令;
2. 脚本:`