Makefile:增量编译、变量与规则
本节学习使用 Makefile 管理 C 语言项目,将重复而复杂的 GCC 编译命令整理成可复用的构建规则。
重点包括程序的编译与链接过程、增量编译原理、Makefile 的目标和依赖、自定义变量与自动变量、模式规则、内置函数,以及编译、清理和安装等常用功能目标。
一、为什么使用 Makefile
Makefile 有三个主要优点:
- 便于管理代码,不必每次手写复杂的编译命令;
- 复用性强,可以反复用于管理和编译不同项目;
- 通过增量编译节省编译时间。
二、程序的编译过程
一个 C 程序从源代码生成可执行文件,大体分为两个阶段。
1. 编译期
编译期包括预处理、编译和汇编。
每个源文件会生成一个对应的 .o 目标文件,例如:
main.c → main.o2. 链接期
把多个 .o 文件以及需要使用的库文件组合起来,最终生成可执行文件。
3. Makefile 为什么能节省时间
第一次编译时,所有源文件都需要生成 .o 文件,因此第一次编译本身并不会节省时间。但是这些 .o 文件会被保留下来。
以后再次执行 make 时:
- 修改过的源文件会重新生成对应的
.o文件; - 没有修改的源文件继续使用原来的
.o文件; - 最后将全部
.o文件重新链接成可执行文件。
Makefile 会比较源文件的修改时间和目标文件的生成时间。
如果源文件比对应的 .o 文件新,就说明源文件被修改过,需要重新编译。
这是一种以存储空间换取编译时间的做法。
三、Makefile 的基本规则
1. 文件名要求
文件名通常写成:
makefileMakefile写好后,需要进入 Makefile 所在目录执行 make。
2. 注释
Makefile 使用 # 表示注释。
3. 一条规则的三个组成部分
目标: 依赖1 依赖2 命令| 组成部分 | 作用 |
|---|---|
| 目标 | 本条规则最终要生成的文件,或者要完成的功能名称 |
| 依赖 | 生成目标所需要的文件 |
| 命令 | 生成目标时真正执行的命令 |
命令行开头必须是一个真正的 Tab,不能用若干空格代替。
4. 默认目标
Makefile 中出现的第一个目标是默认目标。直接执行 make 时,make 会构建第一个目标。
因此,最终要生成的可执行文件一般放在第一条规则中。它依赖的其他规则可以写在后面,make 会根据依赖关系自动查找并执行。
四、自定义变量
Makefile 中定义变量时不需要书写数据类型,变量值默认按字符串处理:
TARGET=myapp引用变量时使用:
$(TARGET)变量名可以包含字母、数字和下划线,但不能以数字开头。通常使用大写字母命名变量。
五、自动变量
自动变量由 make 根据当前规则自动提供。
| 自动变量 | 含义 |
|---|---|
$@ | 当前规则的目标 |
$^ | 当前规则的全部依赖 |
$< | 当前规则的第一个依赖 |
六、模式规则
多个 .c 文件生成对应 .o 文件时,可以写成一条模式规则:
%.o: %.c gcc $< -I../include -c -o $@其中:
%.o表示任意同名的目标文件;%.c表示与目标对应的源文件;$<表示当前规则的第一个依赖;$@表示当前规则的目标。
七、内置函数
1. wildcard
SRCFILE=$(wildcard *.c)wildcard 用于获取当前目录下所有后缀为 .c 的文件名,并保存到 SRCFILE 变量中。
2. patsubst
DSTFILE=$(patsubst %.c,%.o,$(SRCFILE))patsubst 按照指定模式进行替换。这里把 SRCFILE 中所有 .c 文件名替换成对应的 .o 文件名,并保存到 DSTFILE 中。
这样以后增加或删除源文件时,不需要再手工修改目标文件列表,提高了 Makefile 的复用性。
八、常用变量
TARGET=myappCC=gccINCLUDE_PATH=../includeLIBRARY_PATH=../libINSTALL_PATH=/usr/binCFLAGS=-I$(INCLUDE_PATH) -c -WallCPPFLAGS=-DDEBUG| 变量 | 用途 |
|---|---|
TARGET | 保存目标程序名 |
CC | 保存编译命令 |
INCLUDE_PATH | 保存头文件路径 |
LIBRARY_PATH | 保存库文件路径 |
INSTALL_PATH | 保存安装路径 |
CFLAGS | 保存编译选项 |
CPPFLAGS | 保存预处理选项 |
其中,-D 后面需要跟要定义的宏名。示例中的 -DDEBUG 会在编译时定义 DEBUG 宏。
九、功能目标
1. 编译项目
make2. 清理编译结果
make clean删除所有生成的 .o 文件和目标程序。
3. 安装程序
make install把目标程序复制到 /usr/bin。
该目录通常需要管理员权限,因此对应规则中的复制命令需要使用 sudo 或由管理员执行。
4. 卸载程序
如果 Makefile 中定义了 disclean 目标,可以执行:
make disclean它用于删除安装到 /usr/bin 中的目标程序。目标名称是项目自定义的,必须与 Makefile 中实际定义的名称一致。
5. 打印安装路径
make output输出目标程序的完整安装路径。
如果这篇文章对你有帮助,欢迎分享给更多人!





