Makefile 利用-MM和sed自动推导依赖关系

在源码中,我们通常都会包含一系列的头文件,当我们通过Makefile来组织这些源文件参加编译时,需要把相应的头文件也要加到Makefile的依赖当中。如在layerControl_wenston.c中包含#include <cdx_log.h>,那么我们就应该存在以下依赖关系:

layerControl_wenston.o:layerControl_wenston.c cdx_log.h

否则,当我们修改cdx_log.h,如果没有进行clean操作,则会有可能导致我们的修改没有及时的更新。

但是,当遇到一个比较大型的工程目录结构时,你就得必须小心翼翼的处理这些头文件的依赖,修改源码也得修改对应的Makefile,这会产生大量的维护工作,并且极容易造成错误。在编译器如此智能的情况下,我们可以使用c/c++编译器的自动推导功能"-M"选项,即自动寻找源文件中包含的头文件,并生成一个依赖文件,例如执行以下命令:

gcc -M layerControl_wenston.c

其输出是

layerControl_wenston.o:layerControl_wenston.c cdx_log.h

这样就避免了自己手动来决定众多文件的依赖关系了,而是自动由编译器推导生成。如果使用GNU的编译器,需要使用"-MM"参数,否则使用"-M"会把一些标准头文件也包含进来。

如何把编译器这个功能使用起来呢?GNU组织建议编译器为每个源文件自动生成的依赖关系放到一个文件中。为每个*.c文件都产生一个*.dep的Makefile文件,.dep文件中就存放对应.c文件的依赖关系。

下面给出一个规则来产生.dep文件:

%.dep: %.c
	@echo "Creating $@ ..."
	@set -e; \
	rm -rf $@.tmp; \
	$(CC) -E -MM $(filter %.c, $^) > $@.tmp; \
	sed 's,\(.*\)\.o[ :]*,objs/\l.o $@: ,g' < $@.tmp > $@; \
	rm -rf $@.tmp

这个规则的意思如下:
"set -e"的作用是告诉shell,在生成依赖关系文件的过程中,如果出现任何错误就直接退出。shell异常退出的最终表现就是make会告诉我们出错了,从而停止后续的make工作。如果不进行这一设置,当构建依赖文件出错时,make还会继续后面的工作,并最终出错,这不是我们所希望的。
几个需要注意的点:

1.对于规则中的每条命令,make都是在一个新的shell上运行它的。
2.如果希望多条命令在同一个shell中运行,可以使用;将这些命令连在一起。
3.当命令很长时,可以使用"\"将一个命令分成多行书写。
4.$@,用于表示一个规则中的目标,当一个规则中有多个目标时,$@表示任何造成规则命令被执行的目标
5.$^,表示的是规则中的所有先决条件。
6.$<,表示的是规则中的第一个先决条件。

“rm -rf $@.tmp; \”,表示删除每个目标的临时文件*.dep.tmp。

“$(CC) -E -MM $(filter %.c, $^) > $@.tmp; \”,表示为每个.c文件创建一个临时依赖文件*.dep.tmp。

“sed ‘s,(.).o[ :],objs/\l.o $@: ,g’ < $@.tmp > $@; \”,表示通过sed命令把*.dep.tmp文件重定位到*.dep文件中。

最后,通过以下语句引入依赖文件:

SRCS = $(wildcard *.c)
-include $(SRCS:.c=.dep)

以下是我源文件的目录结构和对应Makefile的例子:
在这里插入图片描述
Makefile例子:

SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
DEPS = $(SRCS:.c=.dep)
OUT_BIN = mediaplayer

all: $(OUT_BIN)
-include $(DEPS)

$(OUT_BIN): $(OBJS)
	$(CC) -o $@ $(filter %.o, $^) $(LDFLAGS)

%.o: %.c
	$(CC) $(CFLAGS) -o $@ -c $(filter %.c, $^)

%.dep: %.c
	@echo "Creating $@ ..."
	@set -e; \
	rm -rf $@.tmp; \
	$(CC) -E -MM $(filter %.c, $^) > $@.tmp; \
	sed 's,\(.*\)\.o[ :]*,objs/\l.o $@: ,g' < $@.tmp > $@; \
	rm -rf $@.tmp

.PHONY: clean
clean:
	rm -rf *.o
	rm -rf $(OUT_BIN)
	rm -rf *.dep
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值