从头开始写项目Makefile(二):隐含规则自动推导 .

上一节的Makefile勉强可用,但还写的比较繁琐,不够简洁。对每一个.c源文件,都需要写一个生成其对应的.o目标文件的规则,如果有几百个或上千个源文件,都手动来写,还不是很麻烦,这也不够自动化啊。

这样,我们把生成.o目标文件的规则全部删除掉,就是这样一个Makefile文件:

  1. target_bin : main.o debug.o ipc.o timer.o tools.o  
  2. >---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o  
  3.    
  4. clean:  
  5. >---rm *.o target_bin  
  6.    
target_bin : main.o debug.o ipc.o timer.o tools.o
>---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o
 
clean:
>---rm *.o target_bin
 

这下简洁了不少,这样也能用吗?试试看吧先,make一下:

  1. # make  
  2. cc    -c -o main.o main.c  
  3. cc    -c -o debug.o debug.c  
  4. cc    -c -o ipc.o ipc.c  
  5. cc    -c -o timer.o timer.c  
  6. cc    -c -o tools.o tools.c  
  7. gcc -o target_bin main.o debug.o ipc.o timer.o tools.o  
  8. #  
# make
cc    -c -o main.o main.c
cc    -c -o debug.o debug.c
cc    -c -o ipc.o ipc.c
cc    -c -o timer.o timer.c
cc    -c -o tools.o tools.c
gcc -o target_bin main.o debug.o ipc.o timer.o tools.o
#

原来酱紫都可以啊!!target_bin后面那一群依赖文件怎么生成呢?不是没有生成*.o目标文件的规则了吗?再看屏幕编译输出内容:

  1. cc    -c -o main.o main.c  
  2. cc    -c -o debug.o debug.c  
  3. cc    -c -o ipc.o ipc.c  
  4. cc    -c -o timer.o timer.c  
  5. cc    -c -o tools.o tools.c  
cc    -c -o main.o main.c
cc    -c -o debug.o debug.c
cc    -c -o ipc.o ipc.c
cc    -c -o timer.o timer.c
cc    -c -o tools.o tools.c

怎么长的和之前不太一样呢,尤其是前面那个cc是何物?

其实make可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个*.o文件后都写上类似的命令,因为,我们的 make 会自动推导依赖文件,并根据隐含规则自己推导命令。所以上面.o文件是由于make自动推导出的依赖文件以及命令来生成的。

下面来看看make是如何推导的。

命令make –p可以打印出很多默认变量和隐含规则。Makefile变量可以理解为C语言的宏,直接展开即可(后面会讲到)。取出我们关心的部分:

  1. # default  
  2. OUTPUT_OPTION = -o $@  
  3. # default  
  4. CC = cc  
  5. # default  
  6. COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) –c  
  7. # Implicit Rules  
  8. %.o: %.c  
  9. #  commands to execute (built-in):  
  10. >---$(COMPILE.c) $(OUTPUT_OPTION) $<  
  11.    
# default
OUTPUT_OPTION = -o $@
# default
CC = cc
# default
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) –c
# Implicit Rules
%.o: %.c
#  commands to execute (built-in):
>---$(COMPILE.c) $(OUTPUT_OPTION) $<
 

其中cc是一个符号链接,指向gcc,这就可以解释为什么我们看到的编译输出为cc,其实还是使用gcc在编译。

  1. # ll /usr/bin/cc    
  2. lrwxrwxrwx. 1 root root 3 Dec  3  2013 /usr/bin/cc -> gcc  
  3. #  
# ll /usr/bin/cc  
lrwxrwxrwx. 1 root root 3 Dec  3  2013 /usr/bin/cc -> gcc
#

变量$(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH)都为空。所以%.o: %.c规则命令展开为:

  1. cc    -c -o $@ $<  
cc    -c -o $@ $<

再看屏幕输出编译内容,摘取一条:

  1. cc    -c -o main.o main.c  
cc    -c -o main.o main.c

是不是看出点什么? $@和main.o对应,$<和main.c对应。其实 $@ $< 是两个变量。 $@ 为规则中的目标, $< 为规则中的第一个依赖文件。%.o:%.c 是一种称为模式规则的特殊规则。因为 main.o 符合该模模式,再推导出依赖文件 main.c ,最终推导出整个规则为:

  1. main.o : main.c:  
  2. >--- cc    -c -o main.o main.c  
main.o : main.c:
>--- cc    -c -o main.o main.c
其余几个目标也同样推导。 make 自动推导的功能为我们减少了不少的 Makefile 代码,尤其是对源文件比较多的大型工程,我们的 Makefile 可以不用写得那么繁琐了。

最后,今天的Makefile相对于上一节进化成这个样子了:

  1. target_bin : main.o debug.o ipc.o timer.o tools.o  
  2. >---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o  
  3.    
  4. clean:  
  5. >---rm *.o target_bin  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值