终极目标是makefile中第一个出现的目标。有
两种情况的例外:1. 以“.”号开头,后面不跟"/"的目标。2.作为模式规则的目标。
规则的语法:
TARGETS : PREREQUISITES
COMMAND
...
TARGETS :PREREQUISITES ;COMMAND
COMMAND
...
Makefile对"$"有特殊的含义,如果规则中需要用到"$",则通过“$$”表示。
规则的中心思想是:目标文件的内容由依赖文件决定,依赖文件的任何一处改动,都将导致已经存在的目标文件的内容过期。
依赖类型:
TARGETS : NORMAL-PREREQUISITES | ORDER-ONLY -PREREQUISITES
有时候只希望部分依赖来决定是否重建目标。“order-only”类型的依赖更新不会导致更新目标。
Makefile中的
通配符只能用在规则的
目标,
依赖及
命令上。
自动环境变量
$?表示依赖列表上被改动过的所有文件。
目录搜寻:
VPATH变量,make如果在当前工作目录找不到目标文件或者依赖文件,它会在VPATH指定的路径搜索。
如果当前工作下没有找到目标,而再VPATH指定的搜索路径上找到。目标如果需要更新,会在当前工作目录被生成。
如果目标文件在搜索路径中被找到,并且被更新,如果想在当前路径下被更新的话,需要通过
GPATH变量来指定路径。否则会在当前工作目录被生成。
关键字
vpath PATTERNS DIRECTORIES 可以选择不同类型的目标文件搜索不同的路径。
自动环境变量
$^表示搜索到的文件的完全路径。
变量
.LIBPATTERNS 用来表示依赖文件中对库文件的识别模式。比如依赖文件-lName。.LIBPATTERNS的值可能是lib%.so lib%.a。
Makefile伪目标:
特殊目标
.PHONY, 例如:
.PHONY : main m1
main : m1
@echo "main" > main
@cat < main
m1 :
@echo "m1" > m1
@cat < m1
main : m1
@echo "main" > main
@cat < main
m1 :
@echo "m1" > m1
@cat < m1
不管main m1目标文件在当前目录下是否存在,main和m1的规则命令都会被执行。
强制目标:
clean : FORCE
rm -rf $(objects)
FORCE:
没有依赖和命令,而且它的目标是一个不存在的文件。那么它作为其他目标的依赖总被认为是最新的。作为依赖所在的规则命令总是会被执行。
多目标规则和多规则目标:
多目标规则等效于多个规则,例如:
hello1 hello2 hello3 :
echo $@
等效于
hello1:
echo $@
hello2:
echo $@
hello3:
echo $@
多规则目标的同一个目标在多个规则中的依赖文件最终会合并到一起,但必须只有一个规则有重建此目标的命令。例如:
objects = foo.o bar.o
foo.o : defs.h
bar.o : defs.h test.h
$(objects) : config.h
静态模式:
TARGETS ... : TARGET-PATTERNS : PREQUISITE-PATTERNS
COMMAND
例如:
objects = a.o b.o c.o
$(objects) : %.o : %.c
cc -c $< -o $@
双冒号规则:
当hello目标文件不存在的时候,会顺序的执行依赖文件为h1和h2的规则的命令。当h1被修改,会执行h1作为依赖文件的规则命令,如果h2被修改,会执行h2作为依赖文件的规则命令。
hello :: h1
echo "h1"
touch hello
echo "h1"
touch hello
hello :: h2
echo "h2"
echo "h2"
h1:
touch h1
touch h1
h2:
touch h2
如果目标文件后面的双冒号规则没有依赖文件,则规则命令总是被无条件执行。无论目标文件是否存在。
1 hello ::
2 echo "hello"
3 touch hello
2 echo "hello"
3 touch hello
自动产生依赖:
如果main.c文件中只包含了头文件"defs.h",则执行gcc -M main.c 会输出(如果不考虑标准C库头文件,用-MM):
main.o : main.c defs.h
通过如下模式规则自动为每一个.c文件生成.d文件:
%.d : %c
$(CC) -M $(CPPFLAGS) $< >
$@.$$$$;\
sed 's,\($*\).o[ :]*,\1.o $@ : ,g'
<$@.$$$$ >$@;\
rm -f $@.$$$$
上面的规则会将:
main.o : main.c defs.h
转成
main.o main.d : main.c defs.h
通过下面参考例子来包含.d文件,来重建和更新.d文件:
sources := foo.c bar.c
-include $(sources:.c=.d)
完整的例子:
sources := foo.c bar.c
main : sources
-include $(sources:.c=.d)
%.d : %c
$(CC) -M $(CPPFLAGS) $< >
$@.$$$$;\
sed 's,\($*\).o[ :]*,\1.o $@ : ,g'
<$@.$$$$ >$@;\
rm -f $@.$$$$