在 `Makefile` 中,GNU Make 提供了一组预定义变量,帮助用户方便地管理和控制编译和构建过程。了解这些预定义变量,可以让 `Makefile` 的编写更加简洁和灵活。以下是一些常用的 GNU Make 提供的预定义变量:
### 1. 自动化变量(Automatic Variables)
这些变量在规则(规则的形式是 `target: prerequisites`)的命令部分自动设置,常用于简化规则的编写。
- **$@**: 当前规则的目标文件(target)的名字。
- 例子:在 `target: prerequisites` 中,`$@` 表示 `target`。
- **$<**: 当前规则的第一个依赖文件(prerequisite)的名字。
- 例子:在 `target: srcfile1 srcfile2` 中,`$<` 表示 `srcfile1`。
- **$^**: 当前规则的所有依赖文件(prerequisites)的名字列表,以空格分隔,去除重复的依赖项。
- 例子:在 `target: srcfile1 srcfile2 srcfile1` 中,`$^` 表示 `srcfile1 srcfile2`。
- **$?**: 当前目标比其依赖文件旧的所有依赖文件的名字列表,以空格分隔。
- 例子:在 `target: srcfile1 srcfile2` 中,如果 `srcfile1` 比 `target` 新,`$?` 表示 `srcfile1`。
- **$%**: 目标文件是归档成员(ar 命令产生的库文件)的名字。例如,在 `lib.a(member.o)` 中,`$%` 表示 `member.o`。
- **$(@D)**: 当前目标文件路径中的目录部分。
- 例子:对于目标 `dir/target`,`$(@D)` 表示 `dir`。
- **$(@F)**: 当前目标文件路径中的文件名部分。
- 例子:对于目标 `dir/target`,`$(@F)` 表示 `target`。
- **$(*D)**: 当前第一个依赖文件路径中的目录部分。
- 例子:对于依赖文件 `dir/source`,`$(*D)` 表示 `dir`。
- **$(*F)**: 当前第一个依赖文件路径中的文件名部分。
- 例子:对于依赖文件 `dir/source`,`$(*F)` 表示 `source`。
### 2. 伪目标变量(Phony Targets)
这些变量用于标记一些不实际生成文件的目标,常用来表示一些执行动作(如清理、安装等)。
- **.PHONY**: 伪目标声明,用来告诉 `make` 不检查文件系统中是否存在同名文件。
- 例子:
```makefile
.PHONY: clean
clean:
rm -rf *.o
```
### 3. 默认变量(Default Variables)
这些变量提供了常见的编译和链接器的默认值,可以被覆盖。
- **CC**: 指定 C 编译器的名字,默认为 `cc`。
- 例子:
```makefile
CC = gcc
```
- **CXX**: 指定 C++ 编译器的名字,默认为 `g++`。
- 例子:
```makefile
CXX = g++
```
- **CFLAGS**: 指定传递给 C 编译器的选项。
- 例子:
```makefile
CFLAGS = -g -Wall
```
- **CXXFLAGS**: 指定传递给 C++ 编译器的选项。
- 例子:
```makefile
CXXFLAGS = -g -Wall
```
- **LDFLAGS**: 指定传递给链接器的选项。
- 例子:
```makefile
LDFLAGS = -lm
```
- **CPPFLAGS**: 指定传递给 C 和 C++ 预处理器的选项,通常用于定义宏或包含路径。
- 例子:
```makefile
CPPFLAGS = -I/usr/include
```
- **LDLIBS**: 指定传递给链接器的库文件,通常以 `-l` 开头。
- 例子:
```makefile
LDLIBS = -lpthread
```
### 4. 环境变量(Environment Variables)
GNU Make 允许在 `Makefile` 中使用环境变量,这些变量可以在命令行或环境中定义,然后被 `Makefile` 使用。
- **MAKEFLAGS**: 提供给 `make` 的标志和选项,例如并行执行的 `-j` 选项。
- 例子:
```makefile
MAKEFLAGS = -j4
```
### 5. 特殊目标(Special Targets)
这些变量和规则允许对 `make` 的行为进行特殊的控制。
- **.SUFFIXES**: 指定用于隐式规则的文件后缀列表。
- 例子:
```makefile
.SUFFIXES: .c .o .cpp
```
- **.DEFAULT**: 定义一个没有明确规则的文件的默认规则。
- 例子:
```makefile
.DEFAULT:
@echo "No rule to make target '$@'"
```
### 示例 `Makefile`
以下是一个简单的 `Makefile` 示例,展示了如何使用这些预定义变量:
```makefile
# 定义变量
CC = gcc
CFLAGS = -g -Wall
TARGET = myprogram
# 目标和依赖
$(TARGET): main.o util.o
$(CC) $(CFLAGS) -o $@ $^
# 生成 .o 文件的规则
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
# 清理规则
.PHONY: clean
clean:
rm -f *.o $(TARGET)
```
### 总结
GNU Make 的预定义变量简化了 `Makefile` 的编写和维护。了解并熟练使用这些变量,可以大大提高 `Makefile` 的效率和可读性。通过自动化变量、默认变量和特殊目标的结合,可以创建灵活且强大的构建系统。