CMake基础篇(二)——构建并编译简单Demo

前言:
   本篇举例一个最简单的CMake构建的工程,帮助快速熟悉CMake。

1 CMake简介

  CMake是一种跨平台的编译工具,它语法简单,可以输出各种各样的makefile或project文件。CMake用于产生标准的构建档,使得开发者可以在不同的平台用标准的方式构建软件,实现一次编写编译规则,多个平台相同编译。

2 编写CMakeLists

  CMake的代码是写在CMakeLists文件中,通过执行 cmake 指令生成 Makefile 文件,接着在执行 make 指令编译生成目标文件。
以下用一个最简化的Demo做一个演示,跑一遍构建、编译到运行的过程。
  目录结构如下。

1
2
3
.
├── CMakeLists.txt
└── main.c

  main.c

1
2
3
4
5
6
#include <stdio.h>

void main(void)
{
printf("Hello World!\r\n");
}

  CMakeLists.txt

1
2
3
4
5
6
# CMake最低版本。
cmake_minimum_required(VERSION 3.0)
# 项目名。
project(Test)
# 生成的可执行文件及其依赖。
add_executable(app main.c)

  这两个文件都放到一个目录中,在当前路径下执行指令 cmake . ,开始CMake构建,在当前目录下生成 Makefile 文件,继续执行指令 make ,会按照 Makefile 中的编译规则进行编译,生成可执行文件 app ,执行指令 ./app 即可运行程序。
  只需要编写三行CMakeLists.txt就可以自动完成繁杂Makefile的编写,而且是跨平台的。生成的目录结构如下。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
╰─ tree
.
├── app
├── CMakeCache.txt
├── CMakeFiles
│ ├── 3.22.1
│ │ ├── CMakeCCompiler.cmake
│ │ ├── CMakeCXXCompiler.cmake
│ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ ├── CMakeSystem.cmake
│ │ ├── CompilerIdC
│ │ │ ├── a.out
│ │ │ ├── CMakeCCompilerId.c
│ │ │ └── tmp
│ │ └── CompilerIdCXX
│ │ ├── a.out
│ │ ├── CMakeCXXCompilerId.cpp
│ │ └── tmp
│ ├── app.dir
│ │ ├── build.make
│ │ ├── cmake_clean.cmake
│ │ ├── compiler_depend.internal
│ │ ├── compiler_depend.make
│ │ ├── compiler_depend.ts
│ │ ├── DependInfo.cmake
│ │ ├── depend.make
│ │ ├── flags.make
│ │ ├── link.txt
│ │ ├── main.c.o
│ │ ├── main.c.o.d
│ │ └── progress.make
│ ├── cmake.check_cache
│ ├── CMakeDirectoryInformation.cmake
│ ├── CMakeOutput.log
│ ├── CMakeTmp
│ ├── Makefile2
│ ├── Makefile.cmake
│ ├── progress.marks
│ └── TargetDirectories.txt
├── cmake_install.cmake
├── CMakeLists.txt
├── main.c
├── Makefile
└── README.md

3 build目录

  上面的例子源码和构建编译中间产物全混合在根目录下,工程结构杂乱。下面我们尝试按照CMake的惯例,将构建编译产物生成到build目录中。拿到一个CMake工程后,通常我们要在根目录下手动创建一个临时 build 目录,该目录通常是不需要上传git管理的。

1
2
mkdir build
cd build

  进入build目录后,由于CMakeLists.txt在工程根目录,因此使用以下指令进行构建和编译。

1
2
cmake ..
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
╰─ tree
.
├── build
│ ├── app
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ │ ├── 3.22.1
│ │ │ ├── CMakeCCompiler.cmake
│ │ │ ├── CMakeCXXCompiler.cmake
│ │ │ ├── CMakeDetermineCompilerABI_C.bin
│ │ │ ├── CMakeDetermineCompilerABI_CXX.bin
│ │ │ ├── CMakeSystem.cmake
│ │ │ ├── CompilerIdC
│ │ │ │ ├── a.out
│ │ │ │ ├── CMakeCCompilerId.c
│ │ │ │ └── tmp
│ │ │ └── CompilerIdCXX
│ │ │ ├── a.out
│ │ │ ├── CMakeCXXCompilerId.cpp
│ │ │ └── tmp
│ │ ├── app.dir
│ │ │ ├── build.make
│ │ │ ├── cmake_clean.cmake
│ │ │ ├── compiler_depend.make
│ │ │ ├── compiler_depend.ts
│ │ │ ├── DependInfo.cmake
│ │ │ ├── depend.make
│ │ │ ├── flags.make
│ │ │ ├── link.txt
│ │ │ ├── main.c.o
│ │ │ ├── main.c.o.d
│ │ │ └── progress.make
│ │ ├── cmake.check_cache
│ │ ├── CMakeDirectoryInformation.cmake
│ │ ├── CMakeOutput.log
│ │ ├── CMakeTmp
│ │ ├── Makefile2
│ │ ├── Makefile.cmake
│ │ ├── progress.marks
│ │ └── TargetDirectories.txt
│ ├── cmake_install.cmake
│ └── Makefile
├── CMakeLists.txt
├── main.c
└── README.md