基本语法
Makefile采用top-down的结构,默认会更新最上层的工作目标(all),而下层的工作目标是为了让上层保持在最新状态(如用于删除无用的临时文件的clean工作目标应该放在最下层)。
每条规则的范例如下:
1 | target1 target2 target3 : prerequisite1 prerequisite2 |
说明:
- 如果不存在prerequisite,只检查target是否存在
- command前面要有一个tab,不能用空格
- #表示注释
规则
通配符
makefile中允许使用shell中的~
、*
、?
、[]
、[^]
等通配符。
假想工作目标
假想工作目标(phony target)指的是不代表文件的工作目标,如all、clean。
如果当前工作目录下存在名为clean的文件,clean工作目标就被降级成普通工作目标了。为了解决这一问题,也为了自定义假想工作目标,我们可以将工作目标指定成PHONY,如
1 |
|
值得注意的是:假想工作目标总是尚未更新。因此,将它们作为target则永远不会自动执行。相反,如果将其作为prerequisite,则这个target总会被执行。此外,我们还可以将“假想工作目标”作为“假想工作目标”的必要条件,这样可以让某一个命令先于其它脚本执行。
标准的假想工作目标:
工作目标 | 功能 |
---|---|
all | 执行所有工作 |
install | 安装 |
clean | 删除产生自源代码的文件 |
distclean | 删除编译过程中产生的任何文件(包括configure产生的Makefile) |
TAGS | 建立可供编辑器使用的标记表?? |
info | 从Texinfo源代码来创建GNU info文件?? |
check | 测试 |
空工作目标
有时候我们想要偶尔执行某段代码,又不想让其依存对象被更新,我们就可以建立一个空工作目标:它的工作目标是一个空文件,而且最后一个command是touch
,创建出的新文件可作为这个空工作目标的时间戳。
例如,下面这个规则将会输出自从上次执行过make print
后,变更过的所有文件:
1 | print: *.[hc] |
变量
普通变量的语法位:$(variable-name)
下面是7个核心自动变量:
变量名 | 含义 |
---|---|
$@ | 工作目标文件名 |
$% | 档案文件成员结构中的文件名元素?? |
$< | 第一个必要条件的文件名 |
$? | 时间戳在工作目标之后的所有必要条件 |
$^ | 所有必要条件的文件名(已删掉重复的) |
$+ | 同$^,不过包含重复的 |
$* | 工作目标的主文件名 |
使用自动变量可以大大简化代码,如:
1 | count_words: count_words.o counter.o lexer.o -lfl |
查找文件
对VPATH进行如下赋值:
1 | VPATH = src include |
这样做表示如果没有在当前目录找到所需要的文件,就从src和include文件夹里面找。
这样做没法处理重名文件的问题,make默认会选取找到的第一个文件,此时可以用vpath指令:
1 | vpath pattern directory-list |
这样,之前的VPATH可以这样改写:
1 | vpath %.l %.c src |
模式规则
make可以按照内置规则自动完成一些转换,不必手动指定。例如可以自动地把.c
转换成.o
或可执行文件,把.l
文件自动转换成.c
等等。
这项功能十分强大,例如,我们写了一个helloworld.c
,要想生成可执行文件,Makefile可以只有一行!
1 | helloworld: # 对的!这就行了!连helloworld.c都可以省略! |
在编写模式规则时,经常会用到%
,它大体上等效于shell中的*
,但是只能出现一次。
比如上述helloworld的模式规则如下:
1 | %: %.c |
此外,还有一种过时的后缀规则:如%: %.c
可以略写为.c
,%.o: %.c
可以略写为.c.o
。
模式规则和后缀规则统称为隐含规则。GNU make内置了90个隐含规则,涵盖了C, C++, Pascal, FORTRAN, ratfor, Modula, Texinfo, TEX等等语言。(但是Java没有。。)
很酷的一点是,隐含规则会自动递归地搜索,比如你可以直接从.l文件生成.o文件(省略了.c),而且由此产生的中间文件都会被删除!
下面我们以.c->.o
为例来说明规则的结构:
1 | %.o: %.c |
其中的变量定义如下:
1 | COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c |
这样只要变更CC的值就可以更换C编译器,此外还可以通过设置CFLAGS来设定编译选项。
help命令
这里记录一个打印出当前Makefile定义的目标列表的规则:
1 |
|
特殊工作目标
除了上面已经介绍的.PHONY还有下面这些常用 的工作目标:
- .INTERMEDIATE: 这个特殊工作目标的必要条件会被视为中间文件,会在运行完成后被删除
- .SECONDARY: 被视为中间文件,但不会被删除
- .PRECIOUS: 指示make在出现中断的时候不删除未完成的文件(这个文件太precious了。。)
- .DELETE_ON_ERROR: 与.PRECIOUS效果相反
系列导航