foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
可能有多个隐藏规则,foo.o bar.o会应用隐藏规则,如果有foo.c bar.c,则应用编译c的隐藏规则。
你可以写一个没有recipe的rule,添加依赖,这不影响应用隐藏规则,同时可以添加自己的依赖,比如:
foo.o: foo.h
通常,make在每个没有recipe的target,double-colon rule,上搜索隐藏规则。
如果一个文件只在依赖中提到,那么被认为是一个没有rule的target,也会应用隐藏规则。
如果你不想implicit rule应用到target,那么可以写一个empty recipe,用分号:
target: ;
可以通过命令行选项取消隐藏规则:-r 或者 --no-builtin-rules
可以再没有makefile的目录执行,make -p ,来查看所有的隐藏规则。
内置隐藏规则recipe试用predefined variables,比如CC变量是cc。
使用-R或者--no-bultin-variables,来取消所有隐藏规则使用的变量。
预定义变量分为两类,第一类是编译的程序,比如CC。第二类是参数CFLAGS
一个pattern rule包含%,prerequisite也可以包含%,它是target中%匹配的部分。
%.o : %.c
$@ 目标的名字
$< 第一个依赖
$? 比target新的所有依赖
$^ 所有依赖,不包括order-only依赖。
$| 所有的order-only 依赖,
$*
对于pattern rule,是%匹配的部分。
对于explicit rule,是除去后缀的部分。
1 2 3 4 5 6 7 8 9 10 11 | $ cat Makefile a.c: @echo $* %.o: @echo $* $ make a.c a $ make a.o a |
%匹配的部分叫做stem。
当target pattern不包含斜杠时,文件名中的目录被移除,只匹配文件,但是依赖则会加上去。
%.o: %.c
如果编译src/a.o,那么依赖是src/a.c
A pattern rule can be used to build a given file only if there is a target pattern that matches the file name, and all prerequisites in that rule either exist or can be built
只有当目标和依赖同时满足时,pattern rule才会匹配。
可以有多个目标相同的pattern rule,但是依赖不同,make会优先匹配依赖存在的rule,或者stem最短的rule。
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
%.o : %.f
$(COMPILE.F) $(OUTPUT_OPTION) $<
lib/%.o: lib/%.c
$(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@
编译bar.o,如果存在bar.c则使用第一条rule。
%,通常要定义成双冒号,即双冒号的话,rule是terminal rule,
non terminal match-anything pattern rule不能匹配那些能匹配pattern rule但是依赖不存在的目标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $ cat Makefile %.o: %.c echo %.o %: @echo %: $@ $ make x.o make: *** No rule to make target 'x.o'. Stop. $ cat Makefile %.o: %.c echo %.o %:: @echo %: $@ $ make x.o %: x.o |
如上,如果是%:,则不能匹配x.o,因为x.o匹配了%.o,且x.c不存在,如果定义成双冒号,则可以匹配。