自动生成依赖关系(下)
问题
如何在makeifle中组织.dep文件到指定目录?
解决思路
- 当include发现.dep文件不存在:
- 通过规则和命令创建deps文件
- 将所有.dep文件创建到deps文件夹
- .dep文件中记录目标文件的依赖关系
代码的初步设计
$(DIR_DEPS) :
$(MKDIR)$@
$(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c
@echo "Creating $@ ..."
@set -e; \
$(CC) -MM -E $(filter %.c, $^) | sed 's,\(.*\)\.o[:]*,objs/\1.o:,g'>$@
编程实验
解决方案
.PHONY : all clean
MKDIR := mkdir
RM := rm -fr
CC := gcc
DIR_DEPS := deps
SRCS := $(wildcard *.c)
DEPS := $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
include $(DEPS)
all :
@echo "all"
$(DIR_DEPS) :
$(MKDIR) $@
$(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c
@echo "Creating $@ ..."
@set -e; \
$(CC) -MM -E $(filter %.c, $^) | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g' > $@
clean :
$(RM) $(DIR_DEPS)
实验截图
不是问题的问题
- 为什么一些.dep依赖文件会被重复创建多次?
问题本质分析
- deps文件夹的时间属性会因为依赖文件创建而发生变化
- make发现deps文件夹比对应的目标更新
- 触发相应规则的重新解析和命令的执行
- 。。。。
解决方案的优化
- 使用ifeq动态决定.dep目标的依赖
ifeq ("$(wildcard $(DIR_DEPS))", "")
$(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c
else
$(DIR_DEPS)/%.dep : %.c
endif
编程实验
解决方案的优化
.PHONY : all clean
MKDIR := mkdir
RM := rm -fr
CC := gcc
DIR_DEPS := deps
SRCS := $(wildcard *.c)
DEPS := $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
all :
@echo "all"
ifeq ("$(MAKECMDGOALS)", "all")
-include $(DEPS)
endif
ifeq ("$(MAKECMDGOALS)", "")
-include $(DEPS)
endif
$(DIR_DEPS) :
$(MKDIR) $@
ifeq ("$(wildcard $(DIR_DEPS))", "")
$(DIR_DEPS)/%.dep : $(DIR_DEPS) %.c
else
$(DIR_DEPS)/%.dep : %.c
endif
@echo "Creating $@ ..."
@set -e; \
$(CC) -MM -E $(filter %.c, $^) | sed 's,\(.*\)\.o[ :]*,objs/\1.o : ,g' > $@
clean :
$(RM) $(DIR_DEPS)
实验截图
include暗黑操作一:
-
使用减号(-)不但关闭了include发出的警告,同时也关闭了错误;当错误发生时make将忽略这些错误!
.PHONY : all -include test.txt all: @echo "this is all"
include暗黑操作二:
-
如果include触发规则创建了文件,之后还会发生什么?
.PHONY: all -include test.txt all: @echo "this is all" test.txt: @echo "creating $@...." @echo "other:; @echo "this is other"" > test.txt
include暗黑操作三:
-
如果include包含的文件存在,之后还会发生什么?
.PHONY :all -include test.txt all: @echo "this is all" test.txt:b.txt @echo "this is $@...."
关于include的总结一
-
当目标文件不存在
- 以文件名查找规则,并执行
-
当目标文件不存在,且查找的规则中创建了目标文件
- 将创建成功的目标文件包含进当前makefile
关于include的总结二
- 当目标文件存在
- 将目标文件包含进当前makefile
- 以目标文件名查找是否有相应的规则
- YES : 比较规则的依赖关系,决定是否执行规则命令
- NO: NULL(无操作)
关于include的总结三
-
当目标文件存在,且目标名对应的规则被执行
-
规则中的命令更新了目标文件
- make重新包含目标文件,替换之前包含的内容
-
目标文件未被更新
- NULL(无操作)
-
参考资料:
狄泰软件教学课件