手工编写依赖关系不仅工作量大而且极易出现遗漏,更新也很难及时,修改源或头文件后makefile可能忘记修改。为了解决这个问题,可以用gcc的-M选项自动生成目标文件和源文件的依赖关系。-M选项会把包含的系统头文件以及其所包含的其他系统头文件也找出来了,如果我们不需要输出系统头文件的依赖关系时,可以用-MM选项。

下面我们以一个简单的例子来说明如何自动生成依赖关系:

exm/

main.c

s.c

s.h

makefile文件内容如下:

all:a

src=$(wildcard *.c)

obj:=$(patsubst %.c,%.o,$(src))

ifneq($(MAKECMDGOALS),clean)

-include$(src:.c=.d)

endif

a:$(obj)

gcc$(obj)-o $@

%.d:%.c

set-e;rm -f $@; \

gcc-MM$(CPPFLAGS) $< > $@.

 

; \

sed's,$∗\.o[:]*,\1.o $@ : ,g' < $@.

 

> $@; \

rm-f$@.

 

%.o:%.c

@echo'Buildingfile: $<'

@echo'Invoking:GCC C Compiler'

gcc-O0-g3 -Wall -c -o "$@" "$<"

@echo'Finishedbuilding: $<'

@echo''

其中wildcard作用就是将指定目录下.c文件全部找出,所以这里src=main.cs.c

patsubst作用是把$(src)中的.c全部换为.o,于是obj=main.os.o

include$(src:.c=.d)相当于includemain.ds.d

由于此时这两个文件并不存在,所以会出现下面提示:

makefile:6:main.d:没有那个文件或目录

makefile:6:s.d:没有那个文件或目录

如果不想要这个提示,可以将include替换为-include

尽管一开始找不到.d文件,所以make会报警告。但是make会把include的文件名也当作目标来尝试更新,而这些目标适用模式规则%.d:%c

注意,虽然在Makefile中这个命令写了四行,但其实是一条命令,make只创建一个Shell进程执行这条命令,这条命令分为5个子命令,用;号隔开,并且为了美观,用续行符\拆成四行来写。执行步骤为:

1)set-e命令设置当前Shell进程为这样的状态:如果它执行的任何一条命令的退出状态非零则立刻终止,不再执行后续命令。@表示makefile执行这条命令时不显示出来

2)把原来的.d文件删掉。

3)$<依赖的目标集(即*.c), -MM:表示生成文件依赖关系,$@:表示生成的目标文件(即*.d),$$:表示本身的ProcessID。注意,在Makefile中$有特殊含义,如果要表示它的字面意思则需要写两个$,所以Makefile中的四个$传给Shell变成两个$,两个$在Shell中表示当前进程的id,一般用它给临时文件起名,以保证文件名唯一。

4)这个sed命令比较复杂,就不细讲了,主要作用是查找替换,并加入.d的依赖关系。

5)最后把临时文件删掉。

不管是Makefile本身还是被它包含的文件,只要有一个文件在make过程中被更新了,make就会重新读取整个Makefile以及被它包含的所有文件,现在main.dstack.dmaze.d都生成了,就可以正常包含进来了,相当于在Makefile中添了下面规则:

main.omain.d : main.c s.h

s.os.d : s.c s.h

当源或头文件修改时,如果依赖关系发生变化,执行makefile时将更新具有依赖关系的.d文件,而.d文件的更新又促使make重新读取makefile文件,把新的.d文件包括进来,于是新的依赖关系被建立。

除了上面方法外,还可使用GCC的-MMD-MP -MF -MT选项,如下,可起到同样目的:

all:a

src=$(wildcard *.c)

obj:=$(patsubst %.c,%.o,$(src))

ifneq($(MAKECMDGOALS),clean)

-include$(src:.c=.d)

endif

a:$(obj)

gcc$(obj)-o $@

%.o:%.c

@echo'Buildingfile: $<'

@echo'Invoking:GCC C Compiler'

gcc-O0-g3 -Wall -c -fmessage-length=0 -MMD -MP-MF"$(@:%.o=%.d)"-MT"$(@:%.o=%.d)" -o "$@""$<"

@echo'Finishedbuilding: $<'

@echo''

makefile自动生成依赖关系的更多相关文章

  1. Makefile 7——自动生成依赖关系 三颗星

    后面会介绍gcc获得源文件依赖的方法,gcc这个功能就是为make而存在的.我们采用gcc的-MM选项结合sed命令.使用sed进行替换的目的是为了在目标名前加上“objs/”前缀.gcc的-E选项, ...

  2. Makefile 自动生成依赖

    虽然以前对Makefile有个基本概念,但是真正到自己去写一个哪怕是简单的Makefile时也会遇到不少的麻烦.    现在我有如下文件 dList.h dList.c memory.c debug. ...

  3. Makefile自动生成头文件依赖

    前言 Makefile自动生成头文件依赖是很常用的功能,本文的目的是想尽量详细说明其中的原理和过程. Makefile模板 首先给出一个本人在小项目中常用的Makefile模板,支持自动生成头文件依赖 ...

  4. make自动生成依赖文件的两种形式

    最近编译源文件发现当修改头文件后,make并不会自动把包含此头文件的所有源文件重新编译,而每次都是需要把对应的中间文件清除才能重新编译,非常的麻烦.因此需要make自动对源文件所依赖的头文件进行管理, ...

  5. Makefile 8——使用依赖关系文件

    Makefile中存在一个include指令,它的作用如同C语言中的#include预处理指令.在Makefile中,可以通过include指令将自动生成的依赖关系文件包含进来,从而使得依赖关系文件中 ...

  6. Makeflie自动生成依赖,自动化编译

    在netbeans里开发,有一个重要文件makefile,是用来编译所有的文件. 项目的目录结构如下,扁平的目录结构,如何实现自动化编译,写makefile呢? 第一版 基础版: CC = g++ C ...

  7. Linux Makefile自动生成--config.h

    Linux Makefile自动生成--config.h http://blog.csdn.net/spch2008/article/details/12510805

  8. Makefile 9——为依赖关系文件建立依赖关系

    现在我们再对complicated项目做一些更改,增加程序文件间依赖关系的复杂度. /× main.c ×/ #include"foo.h" int main(void) { fo ...

  9. Makefile 自动产生依赖 ***

    代码如下: 其实这里主要是为每个C文件建立一个同名的后缀为.d.该文件的作用是使用gcc的-M属性来自动生成.o文件的头文件依赖关系. 第1,2,4都好理解. 第2行解释: 使用gcc -M 的属性将 ...

随机推荐

  1. MVC4中的Display Mode简介

    本文地址:http://www.cnblogs.com/egger/p/3400076.html  欢迎转载 ,请保留此链接๑•́ ₃•̀๑! 今天学习MVC4时,看到一个不错的特性"vie ...

  2. jquery的一些属性选择器

    td:contains(Henry)选择td里面所有class为Henry的元素 .siblings()选择相同dom层次的所有其他元素,例如 <ul> <li>第一个< ...

  3. web 标准相关

    摘自:http://www.cnblogs.com/artech/p/restful-web-api-01.html 一.TCP/IP与HTTP TCP/IP是以IP和TCP协议为核心的一整套网络协议 ...

  4. 向下滚动页面加载图片的js

    js代码 scroll.photo.js : window.imgscroll = { options: { target: null, //插入图片的目标位置 img_list: null, //图 ...

  5. JQ二级菜单练习之一~~~

    <div class="nav"> <ul> <li><a href="#">首页</a> < ...

  6. guava学习--File1

    ByteSource:表示一个可读的字节.通常情况下,我们期望的字节来源是一个文件,但它也可以从一个字节数组读取字节. File f1 = new File("D:\\test2.txt&q ...

  7. sql like in 语句获取以逗号分割的字段内的数据

    From:http://www.cnblogs.com/goody9807/archive/2011/07/27/2118107.html sql中的某个字段用“,”分隔数据,需要获取数据的时候直接把 ...

  8. powershell玩转sqlite数据库

    脚本经常需要处理文本,有时候是行列整齐文本.那么powershell脚本处理行列文本有几种方法呢?一种是excel,另外的一些是?access?sqlite? sqlite是一个很小巧的,很方便嵌入到 ...

  9. 转 纯CSS设置Checkbox复选框控件的样式

    Checkbox复选框是一个可能每一个网站都在使用的HTML元素,但大多数人并不给它们设置样式,所以在绝大多数网站它们看起来是一样的.为什么不把你的网站中的Checkbox设置一个与众不同的样式,甚至 ...

  10. Android应用程序“R文件”消失

    其实Android自己维护这一个 public final class R类主要是跟新资源文件,这个R.java无需我们自己去修改,如果你不了解千万不要去修改它,它定义的每个资源值都是唯一的,不会和系 ...