zoukankan      html  css  js  c++  java
  • 第十一篇 自动生成依赖关系(上)

      前面我们涉及到的makefile,都只是考虑到目标文件(.o)依赖于源文件(.c)。然而实际情况却并没有这么简单,我们的源文件一般都是会包含一些自己编写的头文件的,这样的话%.o : %.c这种模式规则的写法是不是就有问题了呢?当源文件不改变而头文件改变时,make解释器是无法根据文件的新旧关系来决定重新编译的,即改变头文件,make不会重新编译。
     
     
      编写func.h func.c main.c三个文件的内容分别如下:
     
     
    makefile程序以及以上三个文件的依赖关系如下:
     
     执行make,可以得到正确的可执行文件,修改func.h中的宏定义,将HELLO宏改为"Hello Makefile",此时,再次执行make,提示文件是最新的,如下所示:
     
    make解释器根据文件新旧关系判断出并不需要重新编译,但是,这并不是我们想要的结果,那么,有什么好的解决方案吗?想必大家首先想到的就是将func.h加入到依赖关系中去,这样头文件的改变,make就能聪明的感知到。
    修改makefile如下:
     

    上图中将func.h加入到了依赖关系中,同时将$^改为$<,因为gcc编译生成目标文件时-c选项只能对应一个文件,而且gcc在编译时是不考虑.h头文件的。

      执行make,输出如下,可见得到了正确的可执行文件:

     
      下面我们来考虑一下这种解决方案存在的问题:
      1、头文件作为依赖条件出现在每个目标对应的规则中(即使这个目标文件与该头文件没有任何关系)。
      2、当头文件改动,任何源文件都将被重新编译(编译低效)。
      3、当项目中头文件数量巨大时,makefile将很难维护。
     
    有没有什么更好的解决方案呢,我们的一个疯狂想法是:
      1、通过命令自动生成对头文件的依赖。
      2、将生成的依赖自动包含进makefile中。
      3、当头文件改动后,自动确认需要重新编译的文件。
     
      为了完成这个疯狂的想法,我们先来进行一些预备知识的学习。
    Linux的sed命令,其具体表述如下:
     
    sed是一个流编辑器,可以对输入输出流进行编辑,我们只用到了字符串替换这一项功能,替换方式为   sed 's:src:des:g',其中,s和g是固定格式,src为待替换的字符串,des为替换后的字符串。
    演示结果如下:
     
    sed还支持正则表达式,如下所示:
    演示结果如下:
     
      (.*).o[ :]*匹配以.o结尾的文件名,包括它的路径结构,后边的[ :]表示文件名后有任意空格或者冒号(:)也可以进行匹配。替换部分则表示在匹配到的文件名前加上前缀objs/。
     
    Linux中的gcc关键编译选项,具体描述如下:
     
    演示如下:
     
    -M选项列出目标文件所有的依赖,包括系统提供的头文件。而-MM选项只列出一些简单依赖,包括我们自己编写的一些文件。使用gcc -MM -E func.c还可以提高效率。
     
    下面我们将gcc的这个特殊选项和sed命令结合在一起,看一下输出结果:
     
    下面介绍一个小技巧:拆分目标的依赖
     
    makefile和执行结果如下所示:
     
       可见,目标的完整依赖可以拆分为部分依赖,而不会改变最终的依赖关系(即拆分后test依旧是依赖a b c这三个伪目标),也不会影响最终行为。依赖中如果存在伪目标,那么伪目标对应的规则一定会被执行,如果依赖中存在伪目标但是该伪目标并没有对应的规则,则默认认为该伪目标已经存在,即依赖条件(伪目标a b c)默认满足。
       将目标的完整依赖拆分为多个部分依赖,则可以将同一个目标的依赖写在多个地方,甚至是写在不同的文件中。
      有了以上的预备知识,我们离上述提到的三个疯狂目标更近了一步,更深入的知识将在下一篇讲解。
     
     
    参考如下:
       狄泰软件教程及课件
       gun make手册
       专业嵌入式软件开发
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    《花好月圆夜》
    关于Url重写
    三大WEB服务器对比分析(apache ,lighttpd,nginx)
    APC 和 Memcache 有什么区别,哪个更好效率更高?
    URL优化不仅仅是静态化重写URL
    php中的静态变量和动态变量的区别框架加载变量时运用
    msicuu.exe (msizap.exe),程序的作用
    显示器接口针脚定义(Dsub15)
    图文教程:DIY全屏开机LOGO详解
    ASP.NET中的媒体播放
  • 原文地址:https://www.cnblogs.com/wanmeishenghuo/p/8421389.html
Copyright © 2011-2022 走看看