(首先声明,本文摘自《跟我一起写 Makefile》作者陈皓 (CSDN),他的MSN是: haoel@hotmail.com。我后面三章基本是直接拷过来的,前面的倒是按照自己的理解码的,例子和解释会有不同。)一般来说,一个target是一个要生成的文件,它会有一个或多个依赖的目标。比如:
foo.o: foo.c
表示要生成的文件为foo.o,而依赖的文件是foo.c。make会自动为我们执行类似于cc foo.c -o foo.o的命令。
这里make在每次运行时会比较依赖文件与目标文件的更新时间,如果foo.c比foo.o更新,那么说明foo.c在上次编译后改动过,所以foo.o会再次编译;否则make假定foo.o已经是最新,不再编译。
对于头文件,我们也应该把它加入到依赖目标集里。就像:
foo.o: foo.c foo.h
这是因为如果不加入头文件的依赖,那么在上次编译后即使foo.h有改动,make也认为foo.o为最新。
make的自动推导可以为目标指定相应的源文件作为依赖目标。
比如makefile这么写:
foo.o:
会等同于
foo.o: foo.c
make它的话,会有如下结果:
$ make foo.o
cc -c -o foo.o foo.c
对于不是文件的目标,我们称之为
“伪目标”,比如clean:,它只是一个标签。我们可以用.PHONY来显式地声明一个目标是伪目标,这样不管是否存在这个文件,目标都被视为是伪目标。比如:
.PHONY: clean
clean:
rm *.o
同样,一旦我们声明
PHONY:foo.o,
那么foo.o就不会被生成。
有一点要注意的是,make会检查文件目标的更新时间,如果已有的目标文件比源文件新,那么这个目标就不会执行;但是伪目标总是会执行。
我们可以
同时指定多个目标,来执行相同的命令,
变量$@指定当前的目标名。比如:
tOne tTwo: foo2.o foo3.o
echo $@
make命令会生成:
$ make tOne
cc -c -o foo2.o src1/foo2.c
cc -c -o foo3.o src2/foo3.c
echo tOne
tOne
多个目标其实会被展开,上面的例子其实等价于:
tOne: foo2.o foo3.o
echo $@
tTwo: foo2.o foo3.o
echo $@
我们可以使用
静态模式来从根据目标来指定依赖的目标集。静态模式的语法为:
: :
先举个例子:
OBJECTS=foo1.o foo2.o
all: foo1.o foo2.o
$(OBJECTS):%.o:src1/%.c
$(CC) -c -o $@ "$<"
这
里是foo1.o和foo2.o;是%.o;为src1/%c。两个pattern中的“%”是必需的。静态模式就是需要从所有targets中抽取匹配“%”的部
分,再由这个部分生成信赖目标集。如之前所说的,$@是目标名,而$<是依赖目标集名。
上面的静态模式展开后等价于:
$foo1.o:src1/foo1.c
$(CC) -c -o foo1.o "src1/foo1.c"
$foo1.o:src2/foo2.c
$(CC) -c -o foo2.o "src1/foo2.c"
再举个例子来加深对静态模式的理解:
tall: tAx tBx tCx
tAx tBx tCx:t%x:%1 %2 %3
A1 A2 A3:
echo $@
B1 B2 B3:
echo $@
C1 C2 C3:
echo $@
make产生的结果为:
$ make tall
echo A1
A1
echo A2
A2
echo A3
A3
echo B1
B1
echo B2
B2
echo B3
B3
echo C1
C1
echo C2
C2
echo C3
C3
阅读(4510) | 评论(0) | 转发(0) |