Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1736442
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: LINUX

2012-04-01 17:39:37

(首先声明,本文摘自《跟我一起写 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
阅读(4349) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~