如何让递归make正确评估子目录先决条件并调用子目录Makefile
问题1:深层.md文件更新触发顶层PDF更新/强制调用子目录Makefile
你的猜测是对的,需要引入FORCE空目标强制每次递归检查子目录修改,同时调整依赖顺序解决更新检测问题:
- 在
./scripts/Makefile.boilerplate开头添加FORCE伪目标定义:
FORCE: .PHONY: FORCE
- 修改同文件中
$(md-sub-y)的规则,添加FORCE依赖,保证每次执行都会进入子目录检查更新:
$(md-sub-y): FORCE @ $(MAKE) -C $(@D) $(MAKECMDGOALS)
- 把
$(TARGET)规则里的$(md-sub-y)从order-only依赖移到普通依赖列表,这样子目录生成的.md更新后,当前目录的拼接目标会重新生成,打通顶层PDF的依赖链:
# 修改前:$(TARGET): $(HEADER) $(md-y) | $(md-sub-y) $(TARGET): $(HEADER) $(md-y) $(md-sub-y) @ cat $^ > $@
问题2:修复顶层clean不递归的问题
修改顶层Makefile的递归规则,保证clean目标会先触发子目录的清理动作:
- 把顶层Makefile中
all clean test: JsonAPI/JsonAPI.md替换为对子目录本身的依赖:
all clean test: JsonAPI
- 新增子目录递归规则:
JsonAPI: FORCE @ $(MAKE) -C $@ $(MAKECMDGOALS)
- 调整顶层clean规则的执行顺序,保证先递归清理子目录,再删除顶层产物:
clean: @ $(RM) *.pdf *.html
因为伪目标clean依赖JsonAPI,make会先执行子目录的clean动作,再执行顶层的删除命令,符合清理逻辑。
问题3:移除命令行传TOPDIR的冗余逻辑
利用make的origin函数判断变量来源,仅在首次执行时赋值TOPDIR,子make会自动继承父进程的变量,不需要手动传递:
在./scripts/Makefile.boilerplate最开头添加如下判断:
ifeq ($(origin TOPDIR), undefined) # 仅当TOPDIR未定义时赋值,此时CURDIR为顶层执行make的目录 TOPDIR := $(CURDIR) endif
之后所有的$(MAKE)调用都可以删掉TOPDIR=$(TOPDIR)参数,变量会自动在递归调用链中传递。
内容的提问来源于stack exchange,提问作者Jamie
相关产品推荐
相关产品推荐

