makefile自动生成依赖

5 篇文章 0 订阅
5 篇文章 0 订阅

此文章是《GNU Make中文手册》中的一个我觉得有必要记录下来的章节,关于如何在makefile中自动生成依赖关系,感谢《GNU Make中文手册》的作者。文章最后为我自己的理解与补充的博文链接。

《GNU Make中文手册》免费下载链接:

http://download.csdn.net/detail/gmpy_tiger/9568503

========================================================================================

4.14 自动产生依赖
       Makefile 中,有时需要书写一些规则来描述一个.o 文件和头文件的依赖关系。例如,如果在 main.c 中使用“#include defs.h”,那么我们可能就需要一个像下边那样的规则来描述当头文件“defs.h”被修改以后再次执行 make,目标“main.o”应该被重建。
       main.o: defs.h
       这样,对于一个大型工程。就需要在 Makefile 中书写很多条类似于这样的规则。并且,当在源文件中加入或删除头文件后,也需要小心地去修改 Makefile。这是一件非常费力、费时并且危险(容易出错误)的工作。为了避免这个讨厌的问题,现代的 c 编译器提供了通过查找源文件中的“#include”来自动产生这种依赖关系的功能。Gcc 通过“-M”选项来实现此功能,使用“-M”选项 gcc 将自动找寻源文件中包含的头文件,并生成文件的依赖关系。例如,如果“main.c”只包含了头文件“defs.h”,那么在 Linxu 下执行下面的命令:

       gcc -M main.c
其输出是:
       main.o : main.c defs.h

既然编译器已经提供了自动产生依赖关系的功能,那么我们就不需要去动手写这些规则的依赖关系了。但是需要明确的是:如果在“main.c”中包含了标准库的头文件,使用 gcc 的“-M”选项时,其输出结果中也包含对标准库的头文件的依赖关系描述。当不需要在依赖关系中考虑标准库头文件时,对于 gcc 需要使用“-MM”参数。

       在使用 gcc 自动产生依赖关系时,所产生的规则中明确的指明了目标是“main.o”。一次在通过.c 文件直接产生可执行文件时,作为中间过程文件的“main.o”在使用完之后将不会被删除。
       在旧版本的 make 中,使用编译器此项功能通常的做法是:在 Makefile 中书写一个伪目标“depend”的规则来定义自动产生依赖关系文件的命令。输入“make depend”将生成一个称为“depend”的文件,其中包含了所有源文件的依赖规则描述。Makefile 中使用“include”指示符包含这个文件。
       在新版本的 make 中,推荐的方式是为每一个源文件产生一个描述其依赖关系的makefile 文件。对于一个源文件“NAME.c”,对应的这个 makefile 文件为“NAME.d”。“NAME.d”中描述了文件“NAME.o”所要依赖的所有头文件。采用这种方式,只有源文件在修改之后才会重新使用命令生成新的依赖关系描述文件“NAME.o”。
       我们可以使用如下的模式规则来自动生成每一个.c 文件对应的.d 文件:

            %.d: %.c
                         $(CC) -M $(CPPFLAGS) $< > $@.XXXX; \
                         sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.XXXX > $@; \

                         rm -f $@.XXXX

       此规则的含义是:所有的.d 文件依赖于同名的.c 文件。
       第一行;使用 c 编译器自自动生成依赖文件($<)的头文件的依赖关系,并输出成为一个临时文件,“XXXX”表示当前进程号。如果$(CC)为 GNU 的 c 编译工具,产生的依赖关系的规则中,依赖头文件包括了所有的使用的系统头文件和用户定义的头文件。如果需要生成的依赖描述文件不包含系统头文件,可使用“-MM”代替“-M”。
       第二行;使用 sed 处理第二行已产生的那个临时文件并生成此规则的目标文件。这里 sed 完成了如下的转换过程。例如对已一个.c 源文件。将编译器产生的依赖关系:
        main.o : main.c defs.h
转成:
        main.o main.d : main.c defs.h
        这样就将.d 加入到了规则的目标中,其和对应的.o 文件文件一样依赖于对应的.c 源文件和源文件所包含的头文件。当.c 源文件或者头文件被改变之后规则将会被执行,相应的.d文件同样会被更新。
       第三行;删除临时文件。

       使用上例的规则就可以建立一个描述目标文件依赖关系的.d 文件。我们可以在Makefile 中使用 include 指示符将描述将这个文件包含进来。在执行 make 时,Makefile所包含的所有.d 文件就会被自动创建或者更新。Makefile 中对当前目录下.d 文件处理可以参考如下:

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

      例子中,变量“sources”定义了当前目录下的需要编译的源文件。变量引用置换“$(sources : .c=.d)”的功能是根据变量“source”指定的.c 文件自动产生对应的.d 文件,并在当前 Makefile 文件中包含这些.d 文件。.d 文件和其它的 makefile 文件一样,make在执行时读取并试图重建它们。其实这些.d 文件也是一些可被 make 解析的 makefile 文件。
需要注意的是 include 指示符的书写顺序,因为在这些.d 文件中已经存在规则。当一个 Makefile 使用指示符 include 这些.d 文件时,应该注意它应该出现在终极目标之后,以免.d 文件中的规则被是 Makefile 的终极规则。关于这个前面我们已经有了比较详细的讨论。

========================================================================================

我个人比较详细的理解博文链接:

http://blog.csdn.net/gmpy_tiger/article/details/51849474

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值