### GNU Make 使用手册关键知识点解析
#### 一、Makefile 文件与 GNU Make 概述
- **GNU Make** 是一种广泛应用于软件构建过程中的自动化工具,它基于一系列预定义的规则来决定何时需要重新编译文件。对于深入理解 Linux 内核等复杂项目而言,掌握 Makefile 的编写技巧至关重要。
- **Makefile 文件** 是 GNU Make 的配置文件,其中包含了各种规则和变量定义,用于指导 make 如何构建项目。理解这些文件有助于更高效地管理项目的构建流程。
#### 二、Makefile 文件结构与编写指南
1. **规则的格式**:Makefile 中的核心部分是规则,它们由目标(target)、先决条件(prerequisites)和命令(commands)组成。
- 目标:指定需要构建的对象。
- 先决条件:目标构建所需的文件。
- 命令:实际执行的 shell 命令。
2. **一个简单的 Makefile 示例**:
```make
all: main.o foo.o
gcc -o program main.o foo.o
main.o: main.c
gcc -c main.c
foo.o: foo.c foo.h
gcc -c foo.c
```
这个简单的 Makefile 定义了如何构建名为 `program` 的可执行文件,以及其依赖的 `.o` 文件。
3. **变量简化 Makefile**:通过定义变量可以简化 Makefile 文件,例如:
```make
CC = gcc
CFLAGS = -Wall -g
all: main.o foo.o
$(CC) $(CFLAGS) -o program main.o foo.o
```
4. **让 make 推断命令**:使用模式规则(pattern rules)和隐含规则(implicit rules)可以让 make 自动推断出构建命令。
5. **另一种风格的 Makefile**:可以使用模式规则和隐含规则来减少重复代码,并使 Makefile 更易于维护。
6. **在目录中删除文件的规则**:通过定义一个清除目标(clean target),可以方便地删除编译产生的临时文件:
```make
clean:
rm -f *.o program
```
#### 三、Makefile 文件的高级特性
1. **Makefile 文件的内容**:Makefile 文件通常包含规则、变量定义和特殊目标等元素。
2. **Makefile 文件的命名**:默认情况下,GNU Make 将查找名为 `Makefile` 或 `makefile` 的文件。
3. **包含其他 Makefile 文件**:使用 `include` 指令可以将其他 Makefile 文件包含到当前 Makefile 中。
```make
include common.mk
```
4. **Makefile 文件的重新生成**:可以通过指定 `.PHONY` 目标来定义 Makefile 的重新生成逻辑。
```make
.PHONY: regenerate_makefile
regenerate_makefile:
# 这里写入重新生成 Makefile 的命令
```
#### 四、编写规则
1. **规则的语法**:规则由目标、先决条件和命令组成,其中目标和先决条件之间用冒号分隔,命令则缩进书写。
2. **使用通配符**:在文件名中使用通配符可以帮助匹配一组文件,如 `*.o` 表示所有 `.o` 文件。
3. **在目录中搜寻依赖**:使用 `VPATH` 变量可以在多个目录中搜索文件,便于处理跨目录的依赖关系。
4. **假想目标**:`.PHONY` 目标是非文件目标,通常用于定义清理(clean)、安装(install)等操作。
#### 五、在规则中使用命令
1. **命令回显**:通过 `-n` 选项可以让 make 打印将要执行的命令,但不实际执行。
2. **执行命令**:命令在规则中通常作为 shell 命令执行。
3. **并行执行**:使用 `-j` 选项可以让 make 同时执行多个命令,加快构建速度。
4. **命令错误**:make 会停止执行如果遇到命令执行失败的情况。
5. **中断或关闭 make**:通过 `Ctrl+C` 可以中断 make 的执行。
6. **递归调用 make**:在 Makefile 中调用 make 来构建子目录中的项目。
#### 六、使用变量
1. **变量引用基础**:使用 `$` 符号来引用变量,如 `$(VAR)`。
2. **变量定义**:通过 `VAR = value` 定义变量。
3. **变量取值**:通过 `$(VAR)` 获取变量的值。
4. **环境变量**:Makefile 可以访问外部环境变量。
5. **特定目标变量**:针对某个目标定义变量。
#### 七、Makefile 文件的条件语句
1. **条件语句**:使用 `ifeq`、`ifdef` 等指令来根据条件执行不同的规则或命令。
2. **条件语句的语法**:如 `ifeq` 的语法:
```make
ifeq ($(VAR),value)
# commands
endif
```
#### 八、文本转换函数
1. **函数调用语法**:使用函数进行文本转换,如 `$(subst old,new,string)`。
2. **字符串替换和分析函数**:`subst`、`patsubst` 等用于字符串替换和模式匹配。
3. **文件名函数**:`notdir`、`basename` 等用于处理文件名。
#### 九、运行 make
1. **指定 Makefile 文件的参数**:通过 `-f` 或 `--file` 选项指定 Makefile 文件。
2. **指定最终目标的参数**:通过 `make target` 指定要构建的目标。
3. **代替执行命令**:使用 `-s` 或 `--silent` 静默模式,只显示命令而不显示命令执行结果。
4. **避免重新编译文件**:通过 `make -r` 或 `make --no-builtin-rules` 可以禁用内置规则。
#### 十、使用隐含规则
1. **隐含规则**:make 自带了一组预定义的规则,可以根据文件扩展名自动推断构建命令。
2. **隐含规则使用的变量**:可以通过设置特定变量来控制隐含规则的行为,如 `CXXFLAGS` 控制 C++ 编译器的选项。
3. **定义与重新定义格式规则**:通过 `%.o : %.c` 这样的模式规则可以自定义隐含规则。
#### 十一、使用 make 更新档案文件
1. **档案成员目标**:使用 `ar` 工具来创建和管理归档文件。
2. **档案成员目标的隐含规则**:make 提供了用于更新归档文件中成员的隐含规则。
3. **使用档案的危险**:需要注意归档文件的更新可能带来的副作用,如不正确的依赖关系。
#### 十二、GNU make 的特点
- **并行构建**:支持同时构建多个文件。
- **条件语句**:提供条件执行功能。
- **文本转换函数**:强大的文本处理能力。
#### 十三、不兼容性和失去的特点
- 随着版本迭代,某些旧功能可能会被废弃或移除,了解这些变化对于保持 Makefile 的兼容性非常重要。
#### 十四、Makefile 文件惯例
1. **Makefile 文件的通用惯例**:遵循一定的约定可以使 Makefile 更易于理解和维护。
2. **Makefile 文件的工具**:利用 Makefile 的高级特性可以构建复杂的项目。
3. **指定命令的变量**:通过变量可以统一管理构建命令中的选项和参数。
4. **安装路径变量**:定义安装路径的变量,如 `PREFIX` 和 `BINDIR`,便于统一控制安装位置。
5. **用户标准目标**:定义常用的目标,如 `clean`、`install` 等,方便用户使用。
GNU Make 是一个功能强大的构建工具,通过对 Makefile 的深入了解和熟练应用,可以极大地提高软件开发效率。通过本文的解析,读者应能更好地理解和应用 Makefile 中的关键概念和技术细节。