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. `$( ';