1.4 Makefile 基本使用
1.4.1 介绍
Makefile
是一个用于便捷一键编译的工具。通过配置Makefile
文件,使用make
工具,可以迅速完成对于复杂项目的编译任务,不用每次键入如前文所述的多条Shell
命令完成编译。
本章节将简单介绍Makefile
的使用,满足基本需求。
关于Makefile
的更多内容请见:
GNU Make 使用手册(中译版)_ZS_Wang_Blogs的博客-CSDN博客
1.4.2 基本语法
- 特殊字符:
字符 | 含义 |
---|---|
$ | 变量符 |
# | 注释符 |
* | 逻辑通配符 |
% | 模式匹配符 |
\ | 转义符 |
- 规则(核心):如下代码属于一条规则,一条规则通常是编译环节的一条命令。
<target>: <source list ...> // <目标>: <依赖列表> // <sourve list> 可以是空, 使用空格分割
<shell command> // <Shell 命令行> // 注意:前方为 \t 而非空格
main: add.c sub.c mul.c div.c main.c
gcc add.c sub.c mul.c div.c main.c -o main
-
变量:
- 自定义变量:
<var>=<text> // <text> 是一个字符串
注意:
Makefile
中字符串没有""
或''
包括,并且可以包含空格。Makefile
中不区分数据类型,因为Makefile
中只存在字符串数据类型。- 预定义变量:(常用)
名称 含义 $@ target / 目标 $^ source list / 依赖列表 $< 依赖列表的第一项 main: add.c sub.c mul.c div.c main.c gcc $^ -o $@
- 引用变量
var=text $(var) // text
-
函数:常用内置函数
wildcard
,patsubst
<var>=$(wildcard <text>) // 将 var 赋值为通配表达式 text 的所有匹配路径的拼接
<var_dst>=$(patsubst <from>, <to>, <string>) // 将 string 与 from 模式匹配并替换为 to 模式
src=$(wildcard *.c)
obj=$(patsubst %.c %.o $(src))
- 伪目标:
.PHONY: <target> // 将 target 设置为伪目标, 伪目标不会检查更新
.PHONY: clean
clean:
rm *.o *.a // 清除编译中间件
1.4.3 工作原理
$ make // 默认调用
$ make <target> // 指定目标调用
注:在配置前调用make
是非法的。
- 在工作目录中检查
makefile
或Makefile
文件,该文件是Makefile
的配置文件。 - 调用目标规则。
目标规则
默认是Makefile
配置文件中的第一个规则,也可以指定目标规则
。 - 检查规则依赖完整。
Shell
命令执行前首先检查相关依赖是否完整。如有依赖文件
缺失,将首先递归
加载依赖文件
,依赖文件
加载规则在Makefile
规则列表中查找。依赖文件
加载规则为自上而下查找,这意味着你可以使用规则的优先级定义模式匹配依赖的加载。 - 检查目标是否需要更新。在完成以上步骤后,若经检查,
目标文件
已存在且依赖文件
时间均早于目标文件
,认为不需要更新,跳过此命令。因此,当项目中途修改Makefile
文件时,你可能需要手动删除生成文件以重新编译。 - 经检查
目标规则
语法正确,依赖文件
完整,目标文件
不存在或需要更新,将执行Shell
命令。
1.4.4 优化编译
-
工作原理中讲到,
Makefile
具有检查依赖与更新的功能,可以充分利用检查与更新机制,局部编译,加速编译速度。例如,对比两段配置文件:
Makefile1
:
main: add.c sub.c mul.c div.c main.c
gcc $^ -o $@
Makefile2
:
main: add.o sub.o mul.o div.o main.o
gcc $^ -o $@
%.o: %.c
gcc $^ -c -o $@
.PHONY: clean
clean:
rm *.o
- 从项目长期看,认为
Makefile2
是优于Makefile1
的。例如,我们需要向main.c
中加入新的功能,此时无需重新编译add.c
等文件,只需编译main.c
与新增功能模块。或者,我们需要改写add.c
模块,只需重新编译add.c
。 - 当然,如果需要,我们可以通过
make clean
清空编译中间件。