自动生成依赖关系

1、引例

值得思考的问题:目标文件.o是否只依赖于源文件.c?编译器是如何编译源文件和头文件的?
解答:预处理器将头文件的代码直接插入源文件,编译器只通过预处理器的源文件产生目标文件。如果规则中以源文件为依赖,命令可能无法执行。因为在修改代码的时候有可能只改动了头文件,源文件没有被修改。如果规则中只是以源文件为依赖目标,Makefile里面某条规则的依赖并不比目标更新,因此命令不同执行,但其实目标所间接依赖的头文件已经被修改,对应的命令应该被执行。这是编译行为带来的缺陷。
解决的方法之一:将所有的头文件作为依赖出现于每个目标对应的规则中,这样头文件被改变之后可以执行规则中的命令。但是,这种方法有缺陷吗?上面“所有的”三个字被加粗,这里的解决方案并不好,虽然可以解决问题。因为当任意一个头文件改动,任何源文件都将被重新编译(编译低效),当项目中头文件数量巨大时,Makefile将很难维护

于是有了下面疯狂的想法:

2、疯狂的想法

(1)通过命令自动生成对头文件的依赖;
(2)将生成的依赖自动包含进makefile中;
(3)当头文件改动后,自动确认需要重新编译的文件。

2.1、实现的原材料

(1)Linux命令sed;
(2)编译器依赖生成选项gcc -MM(gcc -M);
示例代码:

test:
    echo "test=>abc+abc=abc" | sed 's:abc:xyz:g'
    echo "main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
    echo "/a/b/c/d/main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'
    echo "/a/b/c/d/main.o : main.c func.h" | sed 's,\(.*\)\.o[ :]*,x/y/z/\1.o : ,g'
        echo "/a/b/c/d/main.o :::: main.c func.h" | sed 's,\(.*\)\.o[ :]*,x/y/z/\1.o : ,g'
    # add prefix before .o  
    gcc -MM -E main.c | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g' 
    gcc -M -E main.c | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g'

(3)小技巧:如果一个目标是有多个依赖的,那这多个依赖不需要一次性写出来,可以根据需要拆分成多个。
例子:拆分目标的依赖(将目标的完成依赖拆分为多个部分依赖)

.PHONY : a b c

test : a b c
    @echo "$^"

等价于

.PHONY : a b c

test : a b

test : b c

test :
    @echo "$^"


有了原材料,如何将sed和gcc -MM用于makefile,并自动生成依赖关系?
直接开门见山:需要用到makefile里的include。

3、include关键字的使用方法

参考: Makefile中include的暗黑操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值