MakeFile规则(二):自动生成依赖关系

来源:互联网 发布:linux wc l 编辑:程序博客网 时间:2024/05/17 02:58

这一篇,讲述如何去自动生成依赖关系和自动更新依赖关系


<targets …> : <target-pattern> : <prereq-patterns …>
<commands>
… …

1、 makefile中的规则,目标可以是多个。而且多个目标可能同时依赖于一个文件,并且其命令可能

类似,这时候需要用到自动化变量”$@”

例如:
bigoutput littleoutput : 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,后面是参数。Subst是

截取字符串,$@表示目标的集合,像一个数组,注意这里的目标的集合,文件不一定是 .o文件,是目标

,可以是[.d]、[.o]。取出目标,依次执行。

2、 静态模式:语法是最上面的那个
targets:定义了一系列的目标文件,目标的一个集合
target-parrtern:指明了targets的模式,目标集模式
prereq-parrterns:目标的依赖模式,对于target-parrtern形成的模式再进行一次依赖目标的定义。

<target-parrtern>定义成”%.o”,表示<target>集合中的都是以 .o 结尾的。若<prereq-parrterns>定

义成”%.c”,则表示<target-parrtern>的”%.o”文件依赖对应的”%.c”文件,如:若 % 为 mahjong,

则表示 mahjong.o 依赖文件 mahjong.c

例子:
objects = foo.o bar.o
all : $(objects)

$(objects) : %.o : %.c
$(CC) –c $(CFLAGS) $< -o $@

表示:目标all要生成,依赖于 $(objects),而第三句说 $(objects)中的所有.o文件(即”%.o”)要依赖

于对应名字的.c文件(%.c),记住是%.o和%.c的%表示的名字是一样的时候才会自动依赖。

上面例子的后俩句等价于:
foo.o : foo.c
$(CC) –c $(CFLAGS) foo.c –o foo.o
bar.o : bar.c
$(CC) –c $(CFLAGS) bar.c –o bar.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的内容。


3、 自动生成依赖性:
在大型工程中,去手写依赖关系不现实,makefile是能够自动生成依赖关系的。C/C++的编译支持一

个“-M”或是“-MM”的选项,当使用GNU的C/C++编译器时,需要使用”-MM”.不然gcc用“-M”会把标准

库的头文件也包含进来。

使用-M能自动寻找源文件中包含的头文件,并生成一个依赖关系。
若:
main.o : main.c defs.h
表示main.c文件包含头文件:include “defs.h”,则可以这样写:
cc –M main.c

在GNU中使用-M
gcc –M main.c输出是:

main.o : main.c defs.h /usr/include/stdio.h  /usr/include/….

gcc –MM main.c 输出是:
main.o : main.c defs.h

但是如果让编译器的这个-M功能与makefile关联起来。Makefile也需要根据这些源文件重新生成。

GNU把编译器为每一个源文件的自动生成的依赖关系放在一个文件中,为每一个 .c 文件都生成一个 .d的

makefile文件。
[.d]文件中就存放对应[.c]文件的依赖关系,所以我们可以写出[.d]文件和[.c]文件的依赖关系,让make

自动更新或者生成[.d]文件,并把它用include的方式包含在makefile中,这样就可以自动化生成依赖关

系了。

首先生成[.d]文件:

%.d : %.c
@set –e; rm –f $@; \
$(CC) –M $(CPPFLAGS) $< > $@.$$$$; \
sed ’s, \($*\)\.o[:]*,\l.o $@ : , g’ < $@.$$$$ >$@;\
rm –f $@.$$$$

所有的[.d]文件依赖于[.c]文件,然后删除所有目标[.d]文件,第三句为每个[.c]文件生成依赖文件,并

使用$$$$随机编号,可能是:name.d.12456,第四句是使用sed做了一个替换,对于sed需要看相关文档;

最后删除临时文件。

上述例子的意思等价于:
把依赖关系:
main.o : main.c defs.h
转换成:
main.o main.d : main.c defs.h

做完上述例子的事情,[.d]文件就能够自动生成和自动更新了。接下来就是将自动生成的规则放入

makefile中去,使用include命令,来引入到别的makefile中。

例:
sources = foo.c bar.c
include $(sources:.c=.d)

其中.c=.d后面介绍,是做一个替换,将所有[.c]的字符串替换成[.d].


下一篇,介绍makefile的变量

0 0
原创粉丝点击