0%

cmake 迷你系列(一)开启

引言

本系列文章主要讲解 cmake 相关知识,什么是 cmake 呢?用最简单的话说就是跨平台的编译工具。再详细说就不符合本系列的宗旨—迷你了。之所以定义为迷你系列就是用较短的篇幅,把 cmake 讲解一遍,让初学者可以快速上手。好了,废话不多说,直接上手吧。

hello world

万物均以 “hello world ” 开始,本文也不例外,我们就以一个最简单 c 的程序开始,IDE 我这里使用的是 CLion,系统是 macOS Mojave。
项目结构是:

1
2
3
test
|---src
|---main.c

我们在 main.c 中写一个 “hello world”:

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

int main()
{
printf("Hello, World!\n");
return 0;
}

写好如上代码之后,我们发现 main 函数是不能运行的,因为还没有告诉编译器,哪些文件需要编译以及怎么编译。那我们应该怎么做呢?我们在 test 目录添加一个 CMakeLists.txt 文件,结构如下:

1
2
3
4
test
|---src
|---main.c
|---CMakeLists.txt

内容如下:

1
2
3
4
5
6
cmake_minimum_required(VERSION 3.21)
project(test VERSION 0.0.1 LANGUAGES C)

set(CMAKE_C_STANDARD 11)

add_executable(test src/main.c)

我们来分析一下:

  1. 1 行用来指示使用的 cmke 最低版本是多少
  2. 2 行指定项目的名字、版本号、使用的语言
  3. 4 行用来指定 C 的标准
  4. 6 行用来告诉编译器,要添加一个执行文件,名字叫 test,编译的文件是 src 下的 main.c

有了 CMakeLists.txt 文件,main 函数就可以执行起来了。当然,如果我们想要生成可执行文件,我们需要执行以下命令:

1
cmake . && make

然后在项目的根路径就会生成 cmake_install.cmake、CMakeCache.txt、Makefile 以及名为 test 的可执行文件,执行 test 文件,就会打印 “hello world” 了。

📚 Tips

注意 CMakeLists.txt 文件需要放到项目的根路径。

优化你的代码

使你的路径更干净

在上一节,我们执行完 cmake . 命令之后,发现在根路径生成了四个编译文件,原本干净的路径都被这些文件破坏了,当构建的代码多的时候,这些文件更是让人讨厌,所以我们需要执行 cmake -S . -B build 命令,这样,构建相关的文件就会放到当前路径的 build 文件夹下了。我们的项目也就只是我们的代码,没有其他文件干扰了。当我们想要清理的文件时,直接删掉 build 文件夹即可。

指定你的源码路径

在 CMakeLists.txt 文件的最后一行 add_executable(test src/main.c) 我们指定了需要编译的源码文件,如果说 src 下有多个 c 文件,我们都需要一个一个手动添加进来吗?当然不,我们可以使用 aux_source_directory(src SOURCE) 命令,将 src 指定为源码路径,并把该信息保存到了 SOURCE 这个变量中,然后我们就可以使用 add_executable(test ${SOURCE}) 来编译我们的程序,这样无论 src 下添加多少个 c 文件都会编译进来。当然,有时候这样并不好。

我们以一个简单的例子结束本文,首先我们定义一个头文件 utils.h:

1
2
3
4
5
6
#ifndef TEST_UTILS_H
#define TEST_UTILS_H

int add(int,int);

#endif //TEST_UTILS_H

定义头文件时,我们需要编写条件话宏,避免重复引用。该文件中,我们声明了一个函数 int add(int,int)。然后我们创建 utils.c 来实现它:

1
2
3
4
5
6
#include "utils.h"

int add(int a, int b)
{
return a + b;
}

整体的结构如下所示:

1
2
3
4
5
6
test
|---src
|---main.c
|---utils.c
|---utils.h
|---CMakeLists.txt

我们在 main.c 中调用该函数:

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "utils.h"

int main()
{
int sum = add(10, 20);
printf("the sum is %d\n", sum);
return 0;
}

直接运行我们的代码,得到 30 的输出。以上除了添加 utils.h 以及 utils.c 文件之外,并没有修改 CMakeLists.txt 文件,而程序就这样顺利跑起来了,这也是 aux_source_directory(src SOURCE) 命令的功劳。