Makefile自动生成依赖文件,并自动编译

转载于: http://blog.sina.com.cn/s/blog_87c063060101ky45.html

1.关于GCC怎么样自动生成‘依赖’.网上有很多版本,有使用“正则法则”实现的,也有其他方法实现的.

笔者通过比较,觉得最简单的还是Linux内核里面的规则最简单.
 
2.在GCC的命令行加一条这样的语句就OK了. 
  -Wp,-MD,drivers/leds/.XXX.o.d   (其中drivers/leds/.XXX.o.d为依赖文件,里面记录了很多依赖信息)
 
3.就这么简单,来举个例子.Linux内核的一条命令
 
cmd_drivers/leds/led-core.o := arm-linux-gcc -Wp,-MD,drivers/leds/.led-core.o.d  
-nostdinc -isystem /work/tools/gcc-3.4.5-glibc-2.3.6/lib/gcc/arm-linux/3.4.5/include 
-D__KERNEL__ -Iinclude  -include include/linux/autoconf.h 
-mlittle-endian 
-Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing 
-fno-common -Os -marm -fno-omit-frame-pointer 
-mapcs -mno-sched-prolog -mapcs-32 -mno-thumb-interwork 
-D__LINUX_ARM_ARCH__=4 -march=armv4t -mtune=arm9tdmi -malignment-traps -msoft-float 
-Uarm -fno-omit-frame-pointer -fno-optimize-sibling-calls 
-g  -Wdeclaration-after-statement     
-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(led_core)"  
-D"KBUILD_MODNAME=KBUILD_STR(led_core)" 
-c -o drivers/leds/led-core.o drivers/leds/led-core.c
   
4.自己来举个例子吧!
  ①四个文件:def.h  hello.c  main.c  Makefile
   ②四个文件的内容分别为
  def.h:
  #ifndef  __DEF_H
  #define  __DEF_H
  #define  A      5
  void hello();
  #endif   //__DEF_H
   
  hello.c:
  #include<stdio.h>
  #include"def.h"
  void hello()
  {
        printf("hello world!\n");
        printf("A = %d\n",A);
  }
 
  main.c:
  #include<stdio.h>
  #include"def.h"
  int main(void)
  {
        hello();
        return 0;
  }
 
  Makefile:
  PHONY := test
  CROSS_COMPILE =
  CC  = $(CROSS_COMPILE)gcc
 
  CFLAGS := -Wall -Werror -O2 -g
  LDFLAGS =
  test: hello.o main.o
        $(CC) $(LDFLAGS) -o $@  $^
 
  %.o : %.c
        $(CC) $(CFLAGS)   -c -o $@ $<        
  clean:
        rm *.o  test .*.d
 
  ③现象
   在终端输入命令:make
   gcc -Wall -Werror -O2 -g -c -o hello.o hello.c 
   gcc -Wall -Werror -O2 -g -c -o main.o main.c 
   gcc  -o test  hello.o main.o
 
   运行:./test
   hello world!
   A = 5
   
   ④来修改一个文件,把def.h当中的 #define  A      5 改为 #define  A      10  然后再make一下. 
    make: `test' is up to date.
 
   ⑥来修改一下Makefile
  PHONY := test
  CROSS_COMPILE =
  CC  = $(CROSS_COMPILE)gcc
 
  CFLAGS := -Wall -Werror -O2 -g
  LDFLAGS =
  test: hello.o main.o
        $(CC) $(LDFLAGS) -o $@  $^
  dep_file = .$@.d        (特别注意:这里只能用 = ,也就是递归展开 ,而不能用 := ,进行直接展开)
  <读者可以修改观察一下现象,就可以知道 递归展开 = 与 直接展开 := 的区别了,可以感性认识一下二者的区别.> 
   %.o : %.c
        $(CC) $(CFLAGS) -Wp,-MD,$(dep_file)  -c -o $@ $<         
  clean:
        rm *.o  test .*.d
    
   再来 make 一下:
   提示: make: `test' is up to date.
   那么,make clean 之后,再来make看看:
   提示信息:
    gcc -Wall -Werror -O2 -g -Wp,-MD,.hello.o.d  -c -o hello.o hello.c
    gcc -Wall -Werror -O2 -g -Wp,-MD,.main.o.d  -c -o main.o main.c
    gcc  -o test  hello.o main.o
    执行一下看看:./test 
     hello world!
     A = 10
    用ls -al 命令看看: 确实生成了“依赖文件”
    .hello.o.d
    .main.o.d
 
   ⑦再一次修改def.h试试:
    把def.h当中的 #define  A      10 改为 #define  A      20  然后再make一下.
    make: `test' is up to date.
    明明已经生成依赖文件了,为什么make还会提示,说没有更新呢?(后面我们用:时间轴更新 来说明)
 
    笔者也折腾了一阵,后来发现,是“依赖文件”没有"被包含"进Makefile,导致make的“时间轴”没有更新.
 
   ⑧再来修改Makefile:
     在Makefile里面加这么一句:  include .*.o.d  表示包含所以的 .d文件(依赖文件).
     注意:有的需要写成这种形式 -include .*.o.d   
     再一次make:
     提示信息:
     gcc -Wall -Werror -O2 -g -Wp,-MD,.hello.o.d  -c -o hello.o hello.c
     gcc -Wall -Werror -O2 -g -Wp,-MD,.main.o.d  -c -o main.o main.c
     gcc  -o test  hello.o main.o
     果然成功了.
     再来执行一下:  ./test 
     hello world!
     A = 20    
   
5.总结
  在Makefile中,“依赖关系”也是一个比较重要的规则,尤其是“自动生成依赖”.这里笔者举了个简单的例子加以说明.对于Linux,尤其是这种内容,讲起来会比较抽象,尽量自己多去举几个例子,去实践实践,结果很快就可以出来了,也可以加深理解!
   
6.补充
  关于,在Makefile中, include 与 -include 的区别
  通过试验,笔者得出  include 与 -include 存在着用法上的区别,而且内核的Makefile当中,也同时出现过这两种情况.
  在上个实验当中, 用 include.*.o.d 出现了如下错误提示: 
  Makefile:31: .*.o.d: No such file or directory
  make: *** No rule to make target `.*.o.d'.  Stop.
   而用 -include .*.o.d 却解决了问题 
 
在网上找了一篇文章:http://blog.csdn.net/xiaozhi_su/article/details/4202779
 

      指示符include”、-include”和sinclude

       如果指示符include指定的文件不是以斜线开始(绝对路径,如/usr/src/Makefile...),而且当前目录下也不存在此文件;make将根据文件名试图在以下几个目录下查找:

       首先,查找使用命令行选项-I”或者--include-dir”指定的目录,如果找到指定的文件,则使用这个文件;

       否则,继续依此搜索以下几个目录(如果其存在):/usr/gnu/include”、/usr/local/include”和/usr/include”。     

       当在这些目录下都没有找到include”指定的文件时,make将会提示一个包含文件未找到的告警提示,但是不会立刻退出。而是继续处理Makefile的后续内容。当完成读取整个Makefile后,make将试图使用规则来创建通过指示符include”指定的但未找到的文件,当不能创建它时(没有创建这个文件的规则),make将提示致命错误并退出。会输出类似如下错误提示:

       Makefile:错误的行数:未找到文件名:提示信息(No such file or directory

       Make: *** No rule to make target ‘<filename>’. Stop

       通常我们在Makefile中可使用-include”来代替include,来忽略由于包含文件不存在或者无法创建时的错误提示(-”的意思是告诉make,忽略此操作的错误make继续执行)。像下边那样:

       -include FILENAMES...

       使用这种方式时,当所要包含的文件不存在时不会有错误提示、make也不会退出;除此之外,和第一种方式效果相同。以下是这两种方式的比较:

       使用include FILENAMES...”,make程序处理时,如果FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时make程序将会提示错误并退出

 

       使用-include FILENAMES...”的情况是,当所包含的文件不存在或者不存在一个规则去创建它,make程序会继续执行,只有真正由于不能正确完成终极目标重建时(某些必需的目标无法在当前已读取的makefile文件内容中找到正确的重建规则),才会提示致命错误并退出。

 

为了和其它的make程序进行兼容。也可以使用sinclude”来代替-include”(GNU所支持的方式)。

转载于:https://www.cnblogs.com/tureno/articles/6204537.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值