1.规则的语法
targets : prerequisites
command
...
或
targets : prerequisites ; command
command
...
两者区别:第二种command和prerequisites在同一行且用;号隔开
2.在规则中使用通配符
make支持三个通配符:“*”,“?”和“~”
3.文件搜寻
1).VPATH
特殊变量,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件了。
VPATH = src:../headers
2).vpath
关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很灵活的功能。它的使用方法有三种:
a、vpath pattern directories
为符合模式pattern的文件指定搜索目录directories。
b、vpath pattern
清除符合模式pattern的文件的搜索目录。
c、vpath
清除所有已被设置好了的文件搜索目录。
vpath使用方法中的pattern>要包含“%”字符。“%”的意思是匹配零或若干字符,举例:
vpath %.h ../headers
vpath %.c foo
vpath %.c blish
vpath %.c bar
vpath %.c foo:bar
vpath %.c blish
4.伪目标
“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。
当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。
举例:
.PHONY : clean
clean :
rm *.o temp
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
注:一次生成多个目标
.PHONY : cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff
注:伪目标作为依赖
5.多目标
Makefile的规则中的目标可以不止一个,其支持多目标,有可能我们的多个目标同时依赖于一个文件,并且其生成的命令大体类似。于是我们就能把其合并起来
bigoutput littleoutput : text.g
generate text.g -$(subst output,,$@) > $@
其中,- ( s u b s t o u t p u t , , (subst output,, (substoutput,,@)中的“ ” 表 示 执 行 一 个 M a k e f i l e 的 函 数 , 函 数 名 为 s u b s t , 后 面 的 为 参 数 。 这 里 的 这 个 函 数 是 替 换 字 符 串 的 意 思 , “ ”表示执行一个Makefile的函数,函数名为subst,后面的为参数。这里的这个函数是替换字符串的意思,“ ”表示执行一个Makefile的函数,函数名为subst,后面的为参数。这里的这个函数是替换字符串的意思,“@”表示目标的集合,就像一个数组,“$@”依次取出目标,并执于命令。.
6.静态模式
语法:
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
...
举例:
files = foo.elc bar.o lose.o
$(filter %.o,$(files)): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<
7.自动生成依赖性
gcc -M(或-MM) 自动找寻源文件中包含的头文件,并生成一个依赖关系
我们可以写出[.c]文件和[.d]文件的依赖关系,并让make自动更新或自成[.d]文件,并把其包含在我们的主Makefile中,这样,我们就可以自动化地生成每个文件的依赖关系了。
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
这个规则的意思是,所有的[.d]文件依赖于[.c]文件,“rm -f @ ” 的 意 思 是 删 除 所 有 的 目 标 , 也 就 是 [ . d ] 文 件 , 第 二 行 的 意 思 是 , 为 每 个 依 赖 文 件 “ @”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“ @”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“<”,也就是[.c]文件生成依赖文件,“ @ ” 表 示 模 式 “ @”表示模式“%.d”文件,如果有一个C文件是name.c,那么“%”就是 “name”,“ @”表示模式“$$$”意为一个随机编号,第二行生成的文件有可能是“name.d.12345”,第三行使用sed命令做了一个替换,关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。
接下来,我们就要把这些自动生成的规则放进我们的主Makefile中。我们可以使用Makefile的“include”命令,来引入别的Makefile文件
sources = foo.c bar.c
include $(sources:.c=.d)