Make
最后更新于:2022-04-02 03:02:35
[TOC]
> [参考网站](http://www.ruanyifeng.com/blog/2015/02/make.html)
## 语法
### Makefile文件的格式
```
:
[tab]
target : 目标,可以是文件或者伪文件(必须)
prerequisites: 前置条件
tab :第二行 tab 起首
commands: 需要执行的命令
```
### 目标(target)
目标可以是一个文件名,也可以是多个文件名,之间用空格分隔
也可以是伪文件,为了被检测到有文件生成,PHONY
```
.PHONY: clean
clean:
rm *.o
```
Make命令运行时没有指定目标,默认会执行Makefile文件的第一个目标
### 前置条件(prerequisites)
* 前置条件通常是一组文件名,之间用空格分隔
* 只要有一个前置文件不存在,或者有过更新(前置文件的last-modification时间戳比目标的时间戳新),"目标"就需要重新构建
```
result.txt: source.txt
cp source.txt result.txt
```
如果 source.txt 不存在,则需要先创建source.txt
### 命令(commands)
命令(commands)表示如何更新目标文件,由一行或多行的Shell命令组成。
它是构建"目标"的具体指令,它的运行结果通常就是生成目标文件
tab键可以`.RECIPEPREFIX`替换
```
.RECIPEPREFIX = >
all:
> echo Hello, world
```
每行命令在一个单独的shell中执行,这些Shell之间没有继承关系
如:
```
var-lost:
export foo=bar
echo "foo=[$$foo]"
//make var-lost,取不到foo的值
```
可以有三个方法取得 foo
方法一:
```
var-kept:
export foo=bar; echo "foo=[$$foo]"
```
方法二:
```
var-kept:
export foo=bar; \
echo "foo=[$$foo]"
```
方法三:
```
.ONESHELL:
var-kept:
export foo=bar;
echo "foo=[$$foo]"
```
### Makefile文件的语法
#### 注释使用`#`
#### 回声(echoing)
```
test:
# 这是测试
```
执行
```
$ make test
# 这是测试
```
在命令的前面加上@,就可以关闭回声。
```
test:
@# 这是测试
```
现在再执行`make test`,就不会有任何输出
#### 通配符
Makefile 的通配符与 Bash 一致.
主要有星号(*)、问号(?)和 [...] 。比如, `*.o` 表示所有后缀名为o的文件
```
clean:
rm -f *.o
```
#### 模式匹配
主要用到的匹配符是%
`%.o: %.c`
等同于下面的写法。
```
f1.o: f1.c
f2.o: f2.c
```
#### 变量和赋值符
Makefile 允许使用等号自定义变量。
设置 makefile 的变量
```
txt = Hello World
test:
@echo $(txt)
```
获取 bash 的变量需要 两个 `$$`
```
test:
@echo $$HOME
```
```
make test
/home/ant
```
变量赋值
```
VARIABLE = value
# 在执行时扩展,允许递归扩展。
VARIABLE := value
# 在定义时扩展。
VARIABLE ?= value
# 只有在该变量为空时才设置值。
VARIABLE += value
# 将值追加到变量的尾端。
```
#### 内置变量(Implicit Variables)
Make命令提供一系列内置变量
比如,`$(CC)` 指向当前使用的编译器,`$(MAKE)` 指向当前使用的Make工具
```
output:
$(CC) -o output input.c
```
#### 自动变量(Automatic Variables)
1. `$@` 指代当前目标,可指代多个目标
```
a.txt b.txt:
touch $@
```
等于
```
a.txt:
touch a.txt
b.txt:
touch b.txt
```
2. `$<` 指代第一个前置条件
3. `$?` 指代比目标更新的所有前置条件,之间以空格分隔。比如,规则为 t: p1 p2,其中 p2 的时间戳比 t 新,$?就指代p2。
4. `$^` 指代所有前置条件,之间以空格分隔。比如,规则为 t: p1 p2,那么 $^ 就指代 p1 p2 。
5. `$*`指代匹配符 % 匹配的部分, 比如% 匹配 f1.txt 中的f1 ,$* 就表示 f1。
6. `$(@D)` 和 `$(@F)`
$(@D) 和 $(@F) 分别指向 $@ 的目录名和文件名。比如,$@是 src/input.c,那么$(@D) 的值为 src ,$(@F) 的值为 input.c。
7. `$(
';