文档库 最新最全的文档下载
当前位置:文档库 › gcc自动生成依赖文件

gcc自动生成依赖文件

gcc自动生成依赖文件
gcc自动生成依赖文件

那么,编译器的这个功能如何与我们的Makefile联系在一起呢。因为这样一来,我们的Makefile也要根据这些源文件重新生成,让Makefile自已依赖于源文件?这个功能并不现实,不过我们可以有其它手段来迂回地实现这一功能。GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中,为每一个“name.c”的文件都生成一个“name.d”的Makefile文件,[.d]文件中就存放对应[.c]文件的依赖关系。于是,我们可以写出[.c]文件和[.d]文件的依赖关系,并让make自动更新或自成[.d]文件,并把其包含在我们的主Makefile 中,这样,我们就可以自动化地生成每个文件的依赖关系了。

%.d: %.c

@set -e; rm -f $@; \

$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \

sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

rm -f $@.$$$$

执行:make 文件名.d

解释如下:

第一行不用多说;

第二行:@set -e; rm -f $@; \

1. @set -e;

\\ @表示makefile执行这条命令时不显示出来,

\\ set -e; 表示此脚本在执行时返回非零的值,此脚本将终止运行,查找帮助文件如下:

每当命令运行完后,make会检测每个命令的返回码,如果命令返回成功,那么make会执行下一条命令,当规则中所有的命令成功返回后,这个规则就算是成功完成了。如果一个规则中的某个命令出错了(命令退出码非零),那么make就会终止执行当前规则,这将有可能终止所有规则的执行。

如果想忽略错误,可以在命令行前加一个减号“-”。

例:clean:

-rm –f *.o

还有一个全局的办法是,给make加上“-i”或是“--ignore-errors”参数,那么,Makefile中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。还有一个要提一下的make的参数的是“-k”或是“--keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。

ricky@ubuntu:~$ help set

-e Exit immediately if a command exits with a non-zero status.

(Using + rather than - causes these flags to be turned off.\\)

2. rm -f $@;

删除生成的目标文件(即*.d)

第三行: $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \

1. $(CC) -M $(CPPFLAGS) $<

$< 依赖的目标集(即*.c) , -M: 表示生成文件依赖关系,

2. > $@.$$$$

> 重定向输出, $@:表示生成的目标文件(即*.d), $$: 表示本身的Process ID

总的意思就是: 将a.c 文件生成的依赖关系报存在a.d.1212 文件中.(假设a.c 为文件名, 12为Process ID).

备注: 编译依赖文件,并把它的名字根据进程号命名成一个临时文件,用进程号命名是一个技巧,这样重名的可能性很小.

第四行: sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \

这一行用到了sed编辑器, sd是stream editor的缩写,流编辑器的意思.它可以对来自文件或者标准输入的输入流进行变换,

它常被用作管道中的过滤器.详细可以查看帮助文档.

sed命令的结构是s,match,replace,g, 其中s后面的,号就是常见的\,一般写成s\pattern\pattern\的形式,但也可以把\替换成其他符号,比如这里是逗号。g是全局的意思,具体你查查sed。match和replace都是正则表达式。match部分,要先解析makefile的元字符,$*和$@,这个你查查makefile。\(\)是为了后面的引用,后面的\1就是引用这里\(和\)之间括起的部分模式。[ :]也很好理解,你查查正则表达式的文档。

s,match,replace,g 对应s,\($*\)\.o[ :]*,\1.o $@ : ,g

分别对应如下:

s = s

match = \($*\)\.o[ :]* \\ 需要熟悉正则表达式

replace = \1.o $@ : \\ 需要熟悉正则表达式

g = g

即第四行可以写为: sed sed_cmd < $@.$$$$ > $@;

< $@.$$$$ 表示sed 处理的数据为$@.$$$$文件内容,就是上面生成的临时文件(a.d.1212), > $@ 表示将sed处理后的内容重定向到$@(a.12)文件中.

总得意思就是: 将a.d.1212文件中的内容经过sed命令的处理,输出到a.d文件中

备注:用< 来改变读进的数据信道(stdin),使之从指定的档案读进;

用> 来改变送出的数据信道(stdout, stderr),使之输出到指定的档案;

整句话的意思是把临时文件做一个修改然后写入目标文件。这个修改是这样的,临时文件的第一行是

a.o: a.c ...

修改后是

a.o a.d : a.c ...

第5行rm -f $@.$$$$

删除临时文件(a.d.1212)

综上所述:(假设针对的是文件a.c)

%.d: %.c

// 所有的.d文件依赖于.c文件

@set -e; rm -f $@; /

// 删除前期生成的目标文件(a.d)

$(CC) -M $(CPPFLAGS) $< > $@.$$$$; /

// 将编译器针对源文件(a.o)生成的依赖关系保存到临时文件(a.1212)中

// 备注:12为当前进程号

sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; /

// 对临时文件中的内容进行过滤修改保存到目标文件(a.d)中

rm -f $@.$$$$

// 删除临时文件(a.1212)

相关文档