Makefile
Makefile
总览
定义:Makefile是一个自动化编译工具,用于定义文件依赖关系与构建规则
Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释
显示规则
显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出:要生成的目标,目标的依赖文件,生成的命令。其格式如下:
1 | 目标: 依赖文件 |
make会检查目标文件的时间戳,若依赖文件比目标新,则重新执行命令- 若目标文件已存在且依赖无变化,跳过构建(增量编译)
1.伪目标:用于执行非文件生成的操作(如清理、安装等),需通过 .PHONY 显式声明
1 |
|
2.默认目标:一个Makefile中可以定义多个目标,当我们使用make命令但不指定具体的目标时,默认生成第一个目标
3.中间文件目标:临时生成的文件(如 .o 文件),可通过 .INTERMEDIATE 声明,make会在构建完成后自动删除中间文件
1 | .INTERMEDIATE: temp.o |
4.模式目标:使用通配符(%)定义通用规则,简化重复操作
1 | %.o: %.c # 所有 .o 文件依赖同名 .c 文件 |
隐晦规则
隐晦规则是 Make 内置的一些通用构建规则,用于自动推导如何从一种类型的文件生成另一种类型的文件(例如从 .c 生成 .o)。这些规则无需显式写出,Make 会根据文件扩展名自动匹配并应用它们。隐晦规则简化了 Makefile 的编写,尤其在处理常见编译任务时
常见隐晦规则(makefile已经内置,不需要再手动写出来了):
1 | %.o: %.c |
- 其他隐晦规则可用
make -p打印
变量
变量的定义:
1 | VAR_NAME = value |
变量的使用:
1 | $(VAR_NAME) # 或 ${VAR_NAME} |
常见用途:
- 存储编译器名称(
CC = gcc) - 存储编译选项(
CFLAGS = -Wall -O2) - 存储文件列表(
SRC = main.c utils.c)
预定义变量
Makfile中有许多预定义变量,主要用于隐晦规则
| 变量 | 用途 | 默认值 |
|---|---|---|
CC |
C 编译器 | cc |
CFLAGS |
C 编译选项 | 空 |
CXX |
C++ 编译器 | g++ |
CXXFLAGS |
C++ 编译选项 | 空 |
LDFLAGS |
链接选项 | 空 |
自动化变量
用于在规则中动态引用目标或依赖文件
| 变量 | 含义 | 示例(规则中的用法) |
|---|---|---|
$@ |
当前目标文件名 | gcc -c $< -o $@ |
$< |
第一个依赖文件名 | gcc -c $< -o $@ |
$^ |
所有依赖文件(去重) | gcc $^ -o $@ |
$? |
比目标新的依赖文件 | 用于增量编译测试 |
赋值
1.延迟赋值(=)变量值在使用时才展开(递归展开)
1 | A = 1 |
2.立即赋值(:=)变量值在定义时立即展开(静态展开)
1 | A := 1 |
3.条件赋值(?=)仅当变量未定义时才赋值
1 | CFLAGS ?= -Wall # 如果 CFLAGS 未定义,则赋值为 -Wall |
4.追加赋值(+=)向变量追加内容(自动添加空格分隔)
1 | CFLAGS := -Wall |
5.命令行赋值:在使用make命令行工具的时候,可以进行赋值,此时的赋值为覆盖赋值,优先级高于在makefile里面的赋值
6.环境变量:在Makefile里面,可以使用系统的环境变量
文件指示
一个Makfile中可以通过如下方式引用其他的Makefile
1 | include a.mk b.make |
make的工作方式
make 是 linux 下的一个程序软件,Makefile 相当于针对 make 程序的配置文件,当我们执行 make 命令时,make 将会在当前目录寻找 Makefile 文件,然后根据 Makefile 的配置对源文件进行编译。它的工作流程如下:
1、读入当前目录的顶层Makefile
2、读入被include的其它Makefile
3、初始化文件中的变量
4、推导隐晦规则,并分析所有规则
5、为所有的目标文件创建依赖关系链
6、根据依赖关系,决定哪些目标要重新生成
7、执行生成命令
