基本语法
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效果相反
 
系列导航