【Makefile】C文件包含的头文件修改,但不重新编译?

在上一篇 《【linux + makefile】十分钟教你学会makefile的force 》文章的最后,笔者就force的用法在一个示例工程中使用,提出了一个问题:为何build_info.h每次都是新生成的(有修改过),而main.c又是有include “build-info.h”,但main.c却不是每次都重新编译呢?这个到底是不是违反了makefile的基本规则呢?本文将给你答案,通过阅读本文,你将了解到以下内容:
如何保证在c文件中包含的头文件修改了的时候,c文件每次都会被重新编译? 为了更好地展示上诉描述的问题,我们将之前的示例工程稍微复杂化一点点:
整个工程有3个.c文件,a.c/b.c/main.c,其中main.c会调用a.c/b.c中的两个接口,同时main.c会include头文件build_info.h;这个build_info.h每次编译都会重新生成,按照我们之前的写法,我们makefile可能就是这样:
shell = /bin/bash #指定shell使用/bin/bash,否则echo -e可能会出问题echo = echobin = testbuilg_info_h = build_info.hsrc-c-y += a.csrc-c-y += b.csrc-c-y += main.csrc-o = $(patsubst %.c, $(o)%.o, $(src-c-y))all: gen_build_info $(bin)clean: rm -rf $(src-o) $(bin) $(builg_info_h)$(bin) : $(src-o) gcc -o $(o)$@ $(src-o) %.o : %.c gcc -c $ $@force:.phony: force 执行make,我们会发现,跟我们的预期不一样:它虽然会每次都生成build_info.h,但是main.c包含了build_info.h却不会每次都重新编译。这个问题发生的原因,我们来分析下:
在我们的makefile规则中,main.o只依赖于main.c (makefile 第18-19行),而在第二次执行make的时候,main.c显然并没有被修改,所以main.o不会重新生成,自然可执行文件就不会重新生成。这里的问题根源在于,main.c它是依赖于build_info.h的,而这个依赖关系并没有体现在makefile中,所以整个编译流程达不到我们的预期想法。我们尝试下,将main.c的依赖头文件也写入到makefile中,怎么实现呢?
恰好,gcc给了我们强大的支持,它有个非常有用的选项 -md -mf,它可以在生成一个.o的同时也生成它的依赖文件列表,修改后的makefile如下所示:
shell = /bin/bash #指定shell使用/bin/bash,否则echo -e可能会出问题echo = echobin = testbuilg_info_h = build_info.hsrc-c-y += a.csrc-c-y += b.csrc-c-y += main.csrc-o = $(patsubst %.c, $(o)%.o, $(src-c-y))src-c-deps = $(patsubst %.c, $(o).%.o.d, $(src-c-y)) ## 由 a.c ==> .a.o.dall: gen_build_info $(bin)clean: rm -rf $(src-o) $(bin) $(builg_info_h) $(src-c-deps)$(bin) : $(src-o) gcc -o $(o)$@ $(src-o) %.o : %.c# 生成xxx.o的时候,同时生成它的依赖列表,放在文件.xxx.o.d中 gcc -c $ $@force:.phony: force# 在makefile末尾强制包含这些依赖文件-include $(src-c-deps) 测试结果如下所示:
再次执行make,多试几次,一样的结果。
由上可知,经过改造后的makefile是实现了我们的需求,每次build_info.h重新生成,导致main.c包含了build_info.h也会重新编译,而a.c和b.c没有被修改,所以在未执行make clean的情况下,a.c和b.c是不会被重新编译的,每次都是仅仅main.c被再次编译,从而重新生成新的test可执行文件。这样就是已经达到了【当c文件包含的头文件修改了的时候,c文件必须重新编译】的目的。
以上就是关于makefile的高阶用法,基本满足了我们日常工程实践的需求。如果你对该makefile有疑问,欢迎在评论席提出你的疑问,博主很乐意为你解答。
延伸阅读:
【linux + makefile】十分钟教你学会makefile的force


Xilinx可编程逻辑器件设计与开发(基础篇)连载34:Spartan
教你实现用Python自动玩王者荣耀
苹果新任设计掌门人的上位之路
基于FPGA芯片和RISC在图像驱动中的应用
紧随Apple Pay 三星支付24日将公开测试
【Makefile】C文件包含的头文件修改,但不重新编译?
断路器锁具适用各种各样双孔,它的特性是怎样的
通过采用多种编码器实现DSP处理器的低功耗总线的设计
国轩高科第二个在美锂电项目签约落地
德生R101袖珍式高保真收音机的电路剖析及摩机
MiniLED背光:从底层到表现,全新下一代显示技术
英特尔FPGA系列再扩容,打造完美产品矩阵
FAN5400系列USB兼容锂离子电池开关式充电器
HT for Web可视化产品在传统农业中的应用
顺舟智能荣获2023年度海尔智能家电最佳合作奖
安靠封装测试上海守住供应量,产能恢复至100%
比特币期货平台Bakkt为消费者推出了支付应用程序
二次回路的分类
Redmi和小米正在迎接下一代高通旗舰平台骁龙875
华为P10闪存事件持续发酵, 这是要把机会让给小米6吗?