第14课 - 自动生成依赖关系(续)

 1.疯狂想法的具体实现

    

注意事项:

  .dep文件生成后,如果动态的改变头文件间的依赖关系,那么make可能无法检测到这个改变,进而做出错误的编译决策。

 

解决方案:

  • 依赖文件名作为目标加入自动生成的依赖关系

  • 通过include加载依赖文件判断是否执行规则

  • 规则执行时重新生成依赖关系文件

  • 最后加载新的依赖文件

 

编程实验:疯狂的想法 makefile

.PHONY : all clean rebuild

MKDIR := mkdir
RM := rm -fr
CC := gcc

DIR_DEPS := deps
DIR_EXES := exes
DIR_OBJS := objs

DIRS := $(DIR_DEPS) $(DIR_EXES) $(DIR_OBJS)

EXE := app.out
EXE := $(addprefix $(DIR_EXES)/, $(EXE))

SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
DEPS := $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))


all : $(DIR_OBJS) $(DIR_EXES) $(EXE)

ifeq ("$(MAKECMDGOALS)", "all")
-include $(DEPS)
endif

ifeq ("$(MAKECMDGOALS)", "")
-include $(DEPS)
endif

$(EXE) : $(OBJS)
    $(CC) -o $@ $^
    @echo "Success! Target => $@"

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

$(DIRS) :
    $(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) $(DIRS)
    
rebuild :
    @$(MAKE) clean
    @$(MAKE) all
    

运行结果:

  

 

 

func.dep

  objs/func.o deps/func.dep : func.c func.h

 

main.dep

  objs/main.o deps/main.dep : main.c func.h

 

2.小结

  • makefile中可以将目标的依赖拆分写到不同的地方

  • include关键字能够触发相应的规则的执行

  • 如果规则的执行导致依赖更新可能导致再次解释执行相应规则

  • 依赖文件也需要依赖于源文件得到正确的编译决策

  • 自动生成文件间的依赖关系能够提高makefile的移植性

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