参考:
概述
代码编程可执行文件,叫做编译(compile)。先编译这个,再编译那个,叫做构建(build)。
make
是常用的构建工具。构建规则都写在 makefile
里,要学会如何make命令,就必须学会编写makefile文件。
Makefile文件格式
概述
Makefile文件由一系列规则构成,每条规则的形式如下:
- 目标(target):必须
- 前置条件(prerequisites): 可选,但前置条件和命令必须至少存在一个。
- tab
- 命令(commands):可选,但前置条件和命令必须至少存在一个。
1 | <target>: <prerequisites> |
每条规则就明确两件事,构建目标的前置条件是什么,以及如何构建。
目标
目标通常是文件名(多个文件之间用空格分隔),指明make命令所要构建的对象。目标还可以是某个操作的名字,这称为 伪目标 (phony target)。
1 | clean: |
上面代码的目标是clean,它不是文件名,而是一个操作的名字,属于伪目标。
1 | make clean |
但是,如果在当前目录中,正好有一个文件叫做clean,那么这个命令不会执行。因为make发现clean文件已存在,就认为没有必须要重新构建了,就不会执行rm命令。
为了避免这种情况,可以明确声明clean是伪目标。声明伪目标之后,make就不会去检查是否存在一个叫做clean的文件。
1 | # 为声明伪目标 |
如果make命令运行时没有指定目标,默认会执行Makefile文件的第一个目标。
1 | make |
前置条件
前置条件通常是一组文件名,用空格分隔。它指定了目标是否需要重新构建的判断标准,只要有一个前置条件不存在,或者有过更新,目标就需要重新构建。
1 | result.txt: source.txt |
命令
命令表示如何更新目标,它是构建目标的具体指令。
每行命令之前必须有tab键,如果想用其它键,可以使用内置的 .RECIPEPREFIX
来声明。
1 | # 使用 > 替换 tab |
需要注意的是,每行命令在一个单独的shell中执行,这些shell之间没有继承关系。不过可以多个命令写在一行,或使用反斜线(\
),或使用 .ONESHELL
命令。
1 | var-lost: |
1 | var-kept: |
1 | .ONESHELL: |
Makefile文件语法
注释
1 | # 这里是注释 |
回声
默认情况下,make会答应每条命令,然后再执行,这叫做回声(echoing)。
可以在命令前加上 @
,来关闭回声。
由于在构建过程中,需要了解当前执行详情,所以通常只在纯注释和显示的echo命令前面机上@
。
1 | test: |
通配符
Makefile的通配符和Bash一直,主要有 *
, ?
, [...]
。
模式匹配
make命令允许对文件名,进行类似正则运算的匹配,主要用到的匹配符是%
。
使用匹配符,可以将大量同类型的文件,只用一条规则就完成构建。
1 | %.o: %.c |
变量和赋值
Makefile允许使用等号来自定义变量。
调用shell变量,需要在美元符号前多加一个美元符号。
1 | txt = Hello World |
makefile还提供了四个赋值运算符:
1 | VARIABLE = value |
内置变量
make提供了一系列内置变量,比如, $(CC)
指向当前使用的编译器, $(MAKE)
指向当前使用的make工具。
其它内置变量,请参考文档
自动变量
make命令还提供一些自动变量,它们的值与当前的规则有关。
1 | # [email protected] 指代当前目标 |
1 | # $< 指代第一个前置条件 |
1 | # $? 指代比目标更新的所有前置条件, 以空格分隔。 |
1 | # $^ 指代所有前置条件,之间以空格分隔。 |
1 | # $* 指代匹配符 % 匹配的部分 |
1 | # $(@D) 和 $(@F) 分别指向 [email protected] 的目录名和文件名 |
1 | # $(<D) 和 $(<F) 分别指向 $< 的目录名和文件名 |
判断和循环
Makefile使用Bash语法,完成判断和循环。
1 | LIST = one two three |
函数
Makefile还可以使用函数。
1 | $(function arguments) |
1 | # shell 函数用来执行 shell 命令 |
1 | # wildcard 函数用来在 Makefile 中,替换 Bash 的通配符。 |
1 | # subst 函数用来文本替换 |
1 | # patsubst 函数用于模式匹配的替换 |
1 | # 替换后缀名函数的写法是:变量名 + 冒号 + 后缀名替换规则 |
Makefile实例
1 | # 执行多个目标 |