欢迎光临
我们一直在努力

附录2-make与cmake

附录2-make和cmake

1 Make 工具:为什么工程师不直接敲 gcc

想象一下:你的项目有 50 个 .c 文件,每次编译都要敲:

gcc file1.c file2.c file3.c ... file50.c –o my_program.exe

光文件名就能敲到你怀疑人生。而且你改了其中某一个文件,还得重新敲一遍整条命令。

于是有人发明了 Make。Make 是一个自动化工具,它读一个叫 Makefile 的配置文件,知道哪些文件需要编译、按什么顺序编译、改了一个文件之后哪些需要重新编译。

1.1 第一个 Makefile

先让ai助手帮你装make,给他说:国内网络安装make工具,并添加到环境变量。

等装好之后,将1-2的多文件程序复制到一个新文件夹里(我复制在了2-3make里),新建名字为 Makefile 的文件(大小写不能错)。内容如下:

# 用哪个编译器
CC = gcc

# 最终要生成的可执行文件
TARGET = adddemo.exe

# 参与编译的 .c 文件对应的 .o 文件
OBJS = main.o add.o

# 第一条规则是默认目标:把 main.o 和 add.o 链接成 adddemo.exe
$(TARGET): $(OBJS)
$(CC) $(OBJS) -o $(TARGET)

# main.o 依赖 main.c 和 add.h,add.h 变了 main.o 要重新编译
main.o: main.c add.h
$(CC) -c main.c

# add.o 依赖 add.c 和 add.h
add.o: add.c add.h
$(CC) -c add.c

# 清理编译产物:make clean
clean:
del $(OBJS) $(TARGET)

Makefile 里"规则下面的命令"必须以 Tab 开头,不能是空格。写成空格会报 missing separator 错误。这是 Makefile 著名的坑。

现在回到终端,cd 2-3make进入对应文件夹,敲一句:

make

Make 会告诉你它在干什么:

gcc –c main.c
gcc –c add.c
gcc main.o add.o –o adddemo.exe

2-1 make示例

1.2 Make 怎么知道哪些要重新编译?

Makefile 里的每一段都是一个"规则",格式是:

目标: 依赖
命令

意思是:如果"依赖"比"目标"新(说明依赖刚被改过),就重新执行"命令"。

假设你有 10 个文件,第一次 make 全部编译。然后你只改了 file2.c:

第一次 make:10个文件全部编译(因为 .o 还不存在)
↓ 你改了 file2.c,重新 make
第二次 make:只有 file2.c 重新编译(file2.o 比 file2.c 旧),
然后重新链接。其他9个文件纹丝不动。

改哪个编译哪个——这就是 Make 帮工程师省下的海量敲键盘和等待时间。文件越多,收益越大。

1.3 清理产物

编译会生成一堆 .o 和 .exe,想一键清空:

make clean

2-2 make删除

Make 你不用学太细。你只需要知道有这么个东西,它是帮工程师省敲键盘次数的工具。工程里大家不直接写 Makefile,而是用 CMake 来生成 Makefile。如果你想详细了解Makefile的语法,请看:简介 – Makefile教程 – 廖雪峰的官方网站,我之前学Makefile时看的就是这个,写的非常好。

2 CMake:工程级的编译管理

2.1 为什么需要 CMake

你写的程序以后可能不止在你自己电脑上跑。也许你会发给你室友,他用的是 Mac;也许你要把代码传到公司的服务器上,服务器跑的是 Linux。

但有个操蛋的问题是,Makefile不是跨平台的。Windows 上的 Makefile,Mac 和 Linux 不认识。

CMake 解决的就是这个问题,他能跨平台生成Makefile。你写一个 CMakeLists.txt,告诉 CMake"我要编译哪些文件、生成什么名字的程序"。然后 CMake 会根据你当前的操作系统(Windows/Mac/Linux),自动生成对应格式的 Makefile。

2.2 第一个 CMakeLists.txt

ok,先让ai助手帮你装cmake,给他说:国内网络安装cmake工具,并添加到环境变量。

等装好之后,将1-2的多文件程序复制到一个新文件夹里(我复制在了2-4cmake里),新建一个文件,名字必须是 CMakeLists.txt(注意大小写,一个字不能错)。打开它,写入以下内容:

# CMake 要求的最低版本
cmake_minimum_required(VERSION 3.10)

# 项目名
project(adddemo)

# 用哪些源文件生成什么名字的程序
add_executable(adddemo main.c add.c)

就三行,没有一句编译命令。项目要哪几个源文件,一目了然。

2.3 用 CMake 编译

终端输入cd 2-4cmake,进入文件夹,输入:

mkdir build
cd build
cmake –G "MinGW Makefiles" ..
make

这几步在做什么:

  • mkdir build:创建一个叫 build 的文件夹(编译过程中会生成一堆中间文件,别让它们污染你的源码文件夹)。
  • cd build:进入 build 文件夹。
  • cmake -G "MinGW Makefiles" ..:-G "MinGW Makefiles"表示选用mingw编译器,.. 表示上一级目录。这句的意思是"去上一级目录找到 CMakeLists.txt,根据它生成 Makefile,放在当前文件夹里"。
  • make:用刚生成的 Makefile 调用 gcc 编译。
  • 2-3 cmake示例

    2-4 make用cmake生成的Makefile编译

    运行一下:

    .\\adddemo.exe

    8

    2-5 生成二进制文件能正常运行

    为什么要在 build 文件夹里编译?因为 CMake 会生成一大堆中间文件(CMakeCache.txt、各种 .o 等),如果直接放在源码文件夹里,你的项目目录会变得一团乱。

    放到 build 里,想清理就整个文件夹删掉,源码干干净净。这个 build 文件夹以后还会被加到 .gitignore 里(第 5 节会讲 git)。

    以后你接触真实项目,看到的流程基本都是这一套:cmake .. 生成构建配置,make(或 ninja)编译,最后在 build 文件夹里找到可执行文件。学会这一套,你就能自己编译任何开源 C 项目了。

    3 练习题

    题目:把之前所有的项目用 CMake 管理起来——写一个 CMakeLists.txt,生成make,然后在 build 文件夹里 cmake .. && make 编译运行。

    赞(0)
    未经允许不得转载:171主机测评 » 附录2-make与cmake
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址