第13课 - 自动生成依赖关系(下)

1. 问题引入———如何在makefile中组织.dep文件指定目录

解决思路:

include发现.dep文件不存在时

1)通过规则和命令创建deps文件夹
2)将所有.dep文件创建到deps文件夹
3).dep文件记录目标文件的依赖关系

 

初步代码设计:

  

 

编程实验:makefile.1

.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)
    

运行结果:

  



2. 不是问题的问题:为什么一些.dep依赖文件会被重复创建多次?

问题本质分析:

  • deps文件夹时间属性会因为依赖文件创建发生改变

  • make发现deps文件夹对应的目标更新

  • 触发相应的规则重新解析和命令执行

  • 。。。。。。

 

解决方案优化:使用ifeq动态决定.dep目标的依赖

  

 

编程实验:makefile.2

 

.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)
    

运行结果:

   

 

 

 

3. include暗黑操作:

1)使用减号(-)不但关闭了include发出的警告,通过关闭了错误;当错误发生时make忽略这些错误


2)如果include触发规则创建了文件include位置替换为文件的内容

编程实验:makefile.3

.PHONY : all

-include test.txt

all : 
    @echo "this is all"
    
test.txt :
    @echo "creating $@ ..."
    @echo "other : ; @echo "this is other" " > test.txt

运行结果:

  

 

 

 

 

 

 

 

 

3)如果include包含的文件存在,之后还会发生什么?

  include的文件存在时,并且对应的规则及其规则的依赖依赖的时间戳比目标文件的时间戳更新时也存在时,这个文件的规则命令将会被执行

编程实验:makefile.4

.PHONY : all

-include test.txt

all : 
    @echo "this is all"
    
test.txt : b.txt
    @echo "creating $@ ..."
    

运行结果:

  

 

4. 关于include总结

  • 目标文件不存在时:以文件名查找规则,并执行

  • 目标文件不存在时,且查找到的规则创建了目标文件:将创建成功的目标文件中的内容包含进当前makefile

  • 目标文件存在时,将目标文件包含进当前makefile中,以目标文件名查找是否有相应的规则:

1)如果有:比较规则的依赖关系,决定是否执行规则的命令

2)如果没有:无操作

  • 目标文件存在,且目标名对应的规则被执行

1)规则中的命令更新了目标文件:make重新包含目标文件,替换之前包含的内容

2)目标文件未被更新:无操作

 

 

posted @ 2018-09-05 23:57  梦心之魂  阅读(286)  评论(0编辑  收藏  举报