1. CMake概述
CMake 是一个项目构建工具,并且是跨平台的。关于项目构建我们所熟知的还有Makefile(通过 make 命令进行项目的构建),大多是IDE软件都集成了make,比如:VS 的 nmake、linux 下的 GNU make、Qt 的 qmake等,如果自己动手写 makefile,会发现,makefile 通常依赖于当前的编译平台,而且编写 makefile 的工作量比较大,解决依赖关系时也容易出错。
而 CMake 恰好能解决上述问题, 其允许开发者指定整个工程的编译流程,在根据编译平台,自动生成本地化的Makefile和工程文件
,最后用户只需make
编译即可,所以可以把CMake看成一款自动生成 Makefile的工具,其编译流程如下图:
- 蓝色虚线表示使用
makefile
构建项目的过程 - 红色实线表示使用
cmake
构建项目的过程
介绍完CMake的作用之后,再来总结一下它的优点:
- 跨平台
- 能够管理大型项目
- 简化编译构建过程和编译过程
- 可扩展:可以为 cmake 编写特定功能的模块,扩充 cmake 功能
2. CMake的使用
CMake
支持大写、小写、混合大小写的命令。如果在编写CMakeLists.txt
文件时使用的工具有对应的命令提示,那么大小写随缘即可,不要太过在意。
2.1 注释
2.1.1 注释行
CMake
使用 #
进行行注释
,可以放在任何位置。
1 2 |
# 这是一个 CMakeLists.txt 文件 cmake_minimum_required(VERSION 3.0.0) |
2.1.2 注释块
CMake
使用 #[[ ]]
形式进行块注释
。
1 2 3 4 |
#[[ 这是一个 CMakeLists.txt 文件。 这是一个 CMakeLists.txt 文件 这是一个 CMakeLists.txt 文件]] cmake_minimum_required(VERSION 3.0.0) |
2.1 只有源文件
2.1.1 共处一室
-
准备工作,为了方便测试,在我本地电脑准备了这么几个测试文件
-
add.c
1 2 3 4 5 6 7
#include <stdio.h> #include "head.h" int add(int a, int b) { return a+b; }
-
sub.c
1 2 3 4 5 6 7 8
#include <stdio.h> #include "head.h" // 你好 int subtract(int a, int b) { return a-b; }
-
mult.c
1 2 3 4 5 6 7
#include <stdio.h> #include "head.h" int multiply(int a, int b) { return a*b; }
-
div.c
1 2 3 4 5 6 7
#include <stdio.h> #include "head.h" double divide(int a, int b) { return (double)a/b; }
-
head.h
1 2 3 4 5 6 7 8 9 10 11
#ifndef _HEAD_H #define _HEAD_H // 加法 int add(int a, int b); // 减法 int subtract(int a, int b); // 乘法 int multiply(int a, int b); // 除法 double divide(int a, int b); #endif
-
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include <stdio.h> #include "head.h" int main() { int a = 20; int b = 12; printf("a = %d, b = %d\n", a, b); printf("a + b = %d\n", add(a, b)); printf("a - b = %d\n", subtract(a, b)); printf("a * b = %d\n", multiply(a, b)); printf("a / b = %f\n", divide(a, b)); return 0; }
-
-
上述文件的目录结构如下:
1 2 3 4 5 6 7 8
$ tree . ├── add.c ├── div.c ├── head.h ├── main.c ├── mult.c └── sub.c
-
添加
CMakeLists.txt
文件在上述源文件所在目录下添加一个新文件 CMakeLists.txt,文件内容如下:
1 2 3
cmake_minimum_required(VERSION 3.0) project(CALC) add_executable(app add.c div.c main.c mult.c sub.c)
接下来依次介绍一下在 CMakeLists.txt 文件中添加的三个命令:
-
cmake_minimum_required
:指定使用的 cmake 的最低版本- 可选,非必须,如果不加可能会有警告
-
project
:定义工程名称,并可指定工程的版本、工程描述、web主页地址、支持的语言(默认情况支持所有语言),如果不需要这些都是可以忽略的,只需要指定出工程名字即可。1 2 3 4 5 6 7
# PROJECT 指令的语法是: project(<PROJECT-NAME> [<language-name>...]) project(<PROJECT-NAME> [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]] [DESCRIPTION <project-description-string>] [HOMEPAGE_URL <url-string>] [LANGUAGES <language-name>...])
-
add_executable
:定义工程会生成一个可执行程序1
add_executable(可执行程序名 源文件名称)
-
这里的可执行程序名和
project
中的项目名没有任何关系 -
源文件名可以是一个也可以是多个,如有多个可用空格或
;
间隔CMAKE1 2 3 4
# 样式1 add_executable(app add.c div.c main.c mult.c sub.c) # 样式2 add_executable(app add.c;div.c;main.c;mult.c;sub.c)
-
-
-
执行
CMake
命令万事俱备只欠东风,将 CMakeLists.txt 文件编辑好之后,就可以执行
cmake
命令了。1 2
# cmake 命令原型 $ cmake CMakeLists.txt文件所在路径
1 2 3 4 5 6 7 8 9 10 11 12
$ tree . ├── add.c ├── CMakeLists.txt ├── div.c ├── head.h ├── main.c ├── mult.c └── sub.c 0 directories, 7 files robin@OS:~/Linux/3Day/calc$ cmake .
当执行
cmake
命令之后,CMakeLists.txt 中的命令就会被执行,所以一定要注意给cmake
命令指定路径的时候一定不能出错。执行命令之后,看一下源文件所在目录中是否多了一些文件:
1 2 3 4 5 6 7 8 9 10 11 12 13
$ tree -L 1 . ├── add.c ├── CMakeCache.txt # new add file ├── CMakeFiles # new add dir ├── cmake_install.cmake # new add file ├── CMakeLists.txt ├── div.c ├── head.h ├── main.c ├── Makefile # new add file ├── mult.c └── sub.c
我们可以看到在对应的目录下生成了一个
makefile
文件,此时再执行make
命令,就可以对项目进行构建得到所需的可执行程序了。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
$ make Scanning dependencies of target app [ 16%] Building C object CMakeFiles/app.dir/add.c.o [ 33%] Building C object CMakeFiles/app.dir/div.c.o [ 50%] Building C object CMakeFiles/app.dir/main.c.o [ 66%] Building C object CMakeFiles/app.dir/mult.c.o [ 83%] Building C object CMakeFiles/app.dir/sub.c.o [100%] Linking C executable app [100%] Built target app # 查看可执行程序是否已经生成 $ tree -L 1 . ├── add.c ├── app # 生成的可执行程序 ├── CMakeCache.txt ├── CMakeFiles ├── cmake_install.cmake ├── CMakeLists.txt ├── div.c ├── head.h ├── main.c ├── Makefile ├── mult.c └── sub.c
最终可执行程序
app
就被编译出来了(这个名字是在CMakeLists.txt
中指定的)。
2.1.2 VIP 包房
通过上面的例子可以看出,如果在CMakeLists.txt
文件所在目录执行了cmake
命令之后就会生成一些目录和文件(包括 makefile 文件
),如果再基于makefile文件
执行make
命令,程序在编译过程中还会生成一些中间文件和一个可执行文件,这样会导致整个项目目录看起来很混乱,不太容易管理和维护,此时我们就可以把生成的这些与项目源码无关的文件统一放到一个对应的目录里边,比如将这个目录命名为build
: