一、伪目标
什么是伪目标 。实际上 我们之前文章提到过的“clean”就是一个伪目标。
clean:
rm *.o temp
我们并不会生成“clean”这个文件,“伪目标”并不是一个文件,它只是一个标签,由于伪目标不是一个文件,所以make无法生成它的依赖关系,也不能决定是否要执行它,只有当我们明确的指示这个目标他才会生效。 注意:伪目标不能够和文件名重名。
makefile 为了解决重名,定义了 ”.PHONY“ 它能够鲜明的指明一个伪目标,想make说明,不管是否由有个文件,这个目标就是伪目标。
例子:
.PHONY :clean
clean:
rm *.o temp
通常情况下 伪目标是没有依赖文件的,但是我们也可以为伪目标指定所依赖的文件。伪目标也可以作为”默认目标“,只要将其放在第一个。
比如果你的makefile需要一口气生成若干个可执行文件,而你只想敲一个make就完事,并且所有的目标文件都写在一个Makefile 中,你就可以使用伪目标 这个特性。
all : prog1 prog2 prog3
.PHONY :all
prog1 : prog1.o untils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog1 prog1.o
prog1 : prog3.o untils.o sort.o
cc -o prog3 prog3.o utils.o sort.o
Makefile 的特性是 Makefile中的第一个目标会被作为默认目标,我们声明了一个”all“的伪目标,由于为目标的特性是总是被执行,所以其他三个目标就总是不如all新,这就达到可我们一口气生成多个目标的目的了
伪目标也是可以成为以来的
.PHONY clean all cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj:
rm *.o
cleandiff:
rm *.diff
就像一个主函数 ,里面执行各种函数一样,我们可以输入不同clean~ 来达到清理不同文件的目的。
二、多目标
Makefile的规则中的目标可以不止一个,其支持多目标,我们可以多个目标同时依赖于一个文件,并且其生成的命令大体类似。于是我们就能把其合并起来。当然多个目标生成规则的执行命令时同一个。我们可以使用一个自动化变量“$@”,这个变量表示目前规则所有目标的集合。
bigoutput littleoytput : text.g
generate text.g -$(subst output,,$@) > $@
这两行命令等价于
bigoutput :text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput
其中-$(subst output,,$@)中的“$”表示执行一个MakeFile的函数。函数名为subst,后面的时参数。
“$@”表示目标的集合,就像一个数组,“$@”依次取出目标,并执行命令。
三、静态模式
静态模式可以更加容易的定义多目标的规则,可以让我们的规则更加的灵活
eg:
<targets ...>: <target-pattern> : <prereq-pattern ...>
<command>
...
targest定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern 是指明了targets的模式。也就是目标模式
prereq-parrterns 是目标的依赖模式。他对target-parrtern 形成的模式再进行依次依赖目标的定义
例子一:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o : %.c
$(CC) -c $(CFLAGS) $ < -o $@
这个例子中指明了,我们的目标是从$Objects中获取,“%.o”表明要所有以.o 结尾的目标,也就是“foo.o bar.o” 也就是变量$Object 集合的所有模式,而依赖模式“%.c”则是取模式“%.o”的“%”,也就是“foo bar” ,并为其加下“.c”的后缀,于是我们的以来目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动变化类型,“$<”表示所有的依赖目标集(也就是foo.c bar.c),“$@”表示目标集(也就是foo.o bar.o)
所以上面的规则展开后等价于
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
如果我们的“%.o”有几百个,我们就可以用这种 “静态模式规则”,提升很多效率。
例子二:
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 &<
$(filter %.o,$(files))表示调用Make file的filter函数,过滤“$filter”集,只要其中模式为“%.o”