8.0 make的运行
# make 的运行
# make 的退出码
make 命令执行后有三个退出码:
0 : 表示成功执行
1 : 如果 make 运行时出现任何错误,其返回 1
2 : 如果你使用了 make 的 “-q” 选项,并且 make 使得一些目标不需要更新,那么返回 2。
# 指定 Makefile
GNU make 找寻默认的 Makefile 的规则是在当前目录下依次找三个文件 ——“GNUmakefile”、“makefile” 和 “Makefile”。其按顺序找这三个文件,一旦找到,就开始读取这个文件并执行。
当前,我们也可以给 make 命令指定一个特殊名字的 Makefile。要达到这个功能,我们要使用 make 的 -f 或是 --file 参数( --makefile 参数也行)。例如,我们有个 makefile 的名字是 “hchen.mk”,那么,我们可以这样来让 make 来执行这个文件:
make –f hchen.mk
如果在 make 的命令行中不只一次地使用了 -f 参数,那么,所有指定的 makefile 将会被连在一起传递给 make 执行。
# 定义模式规则
模式规则中,至少在规则的目标定义中要包含 % ,否则,就是一般的规则。目标中的 % 定义表示对文件名的匹配,** % 表示长度任意的非空字符串。** 例如: %.c 表示以 .c 结尾的文件名(文件名的长度至少为 3),而 s.%.c 则表示以 s. 开头, .c 结尾的文件名(文件名的长度至少为 5)。
如果 % 定义在目标中,那么,依赖中的 % 的值决定了目标中的 % 的值,也就是说,依赖中的模式的 % 决定了目标中 % 的样子。例如有一个模式规则如下:
%.o : %.c ; <command ......>;
其含义是,指出了怎么从所有的 .c 文件生成相应的 .o 文件的规则。如果存在文件 a.c b.c ,那么要生成的目标就是 a.o b.o .
一旦依赖目标中的 % 模式被确定,那么,make 会被要求去匹配当前目录下所有的文件名,一旦找到,make 就会规则下的命令,所以,在模式规则中,目标可能会是多个的,如果有模式匹配出多个目标,make 就会产生所有的模式目标,此时,make 关心的是依赖的文件名和生成目标的命令这两件事。
# 模式规则示例
下面这个例子表示了,把所有的 .c 文件都编译成 .o 文件.
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
2
其中, $@ 表示所有的目标的挨个值, $< 表示了所有依赖目标的挨个值。这些奇怪的变量我们叫 “自动化变量”,后面会详细讲述。
# 自动化变量:
自动化变量 ** 把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。** 这种自动化变量只应出现在规则的命令中。
下面是所有的自动化变量及其说明:
$@: 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,$@就是匹配于目标中模式定义的集合。$%: ** 仅当目标是函数库文件中,表示规则中的目标成员名。** 例如,如果一个目标是foo.a(bar.o),那么,$%就是bar.o,$@就是foo.a。如果目标不是函数库文件(Unix 下是.a,Windows 下是.lib),那么,其值为空。$<: ** 依赖目标中的第一个目标名字。** 如果依赖目标是以模式(即%)定义的,那么$<将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$? : ** 所有比目标新的依赖目标的集合。** 以空格分隔。
$^ : ** 所有去重的依赖目标的集合。** 以空格分隔。如果在依赖目标中有多个重复的,那么这个变量会去除重复的依赖目标,只保留一份。
$+ : 不去除重复的依赖目标的集合。和 $^ 很像。
$* : ** 这个变量表示目标模式中 % 及其之前的部分。** 如果目标是 dir/a.foo.b ,并且目标的模式是 a.%.b ,那么, $* 的值就是 dir/foo 。这个变量对于构造有关联的文件名是比较有效。
- 如果目标中没有模式的定义,那么
$*也就不能被推导出 - 如果目标文件的后缀是 make 所识别的,那么
$*就是除了后缀的那一部分。例如:如果目标是foo.c,因为.c是 make 所能识别的后缀名,所以,$*的值就是foo。
(这个特性是 GNU make 的,很有可能不兼容于其它版本的 make,所以,你应该尽量避免使用$*,除非是在隐含规则或是静态模式中。如果目标中的后缀是 make 所不能识别的,那么$*就是空值。)
# MAKECMDGOALS
make 的环境变量叫 MAKECMDGOALS ,这个变量中会存放最终目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。这个变量可以让你使用在一些比较特殊的情形下。比如下面的例子:
sources = foo.c bar.c
ifneq ( $(MAKECMDGOALS),clean)
include $(sources:.c=.d)
endif
2
3
4
基于上面的这个例子,只要我们输入的命令不是 “make clean”,那么 makefile 会自动包含 “foo.d” 和 “bar.d” 这两个 makefile。