如何在Makefile中使用通配符消除重复的编译规则?
解决方案
你之前通配符失效的原因:直接把通配符写在目标依赖里时,Make只会匹配当前已经存在的.so文件,编译前这些文件还不存在,所以依赖列表会被展开为空,自然不会执行对应编译任务。你可以通过Make模式规则+源文件自动扫描解决重复配置和自动识别目标的需求:
第一步:编写通用模式规则替换重复的单天编译规则
用%作为通配符匹配日期标识,一套规则覆盖所有天的编译逻辑:
# 匹配所有 aocYYYYdayXX.so 目标的通用编译规则 aoc%.so: $(ADVENTS_SRC)%/aoc%.scm aoc-files.so $(CSC) $(INCLUDE_FLAGS) $(LIBFLAGS) $< -j $* -emit-types-file $*.types -o $@ $(CSC) $(INCLUDE_FLAGS) $(IMPORTFLAGS) $*.import.scm # 匹配所有 import.so 目标的通用规则 %.import.so: %.so $(CSC) $(INCLUDE_FLAGS) $(IMPORTFLAGS) $*.import.scm
这里内置变量$*会自动替换为模式匹配中%捕获到的内容(比如2015day01),不需要手动写每个日期的标识。
第二步:自动扫描源文件生成依赖列表
先扫描对应年份目录下所有的单天源文件,再把源文件后缀替换为.so,自动生成完整的依赖列表,不需要手动追加:
# 自动扫描2015年所有单天源文件,生成对应的.so依赖列表 AOC2015_DAY_SRCS := $(wildcard $(ADVENTS_SRC)2015/aoc2015day*.scm) AOC2015_DAY_TARGETS := $(patsubst $(ADVENTS_SRC)2015/aoc2015day%.scm,aoc2015day%.so,$(AOC2015_DAY_SRCS)) # 主目标依赖自动生成的列表,不需要手动修改 advent2015: $(ADVENTS_SRC)2015/advent2015.scm $(AOC2015_DAY_TARGETS) $(CSC) $(INCLUDE_FLAGS) $< -d3 -O2 -compile-syntax -o $@
扩展到后续年份的优化
如果之后要加2016、2017等年份的代码,可以再封装一层变量进一步减少重复:
# 只需要在这里加年份即可自动生成对应年份的主目标 AOC_YEARS := 2015 2016 2017 define gen_year_target AOC$(1)_DAY_SRCS := $$(wildcard $$(ADVENTS_SRC)$(1)/aoc$(1)day*.scm) AOC$(1)_DAY_TARGETS := $$(patsubst $$(ADVENTS_SRC)$(1)/aoc$(1)day%.scm,aoc$(1)day%.so,$$(AOC$(1)_DAY_SRCS)) advent$(1): $$(ADVENTS_SRC)$(1)/advent$(1).scm $$(AOC$(1)_DAY_TARGETS) $$(CSC) $$(INCLUDE_FLAGS) $$< -d3 -O2 -compile-syntax -o $$@ endef # 自动生成所有年份的主目标规则 $(foreach year,$(AOC_YEARS),$(eval $(call gen_year_target,$(year)))) # 总目标编译所有年份 all: $(foreach year,$(AOC_YEARS),advent$(year))
内容的提问来源于stack exchange,提问作者Mark Fisher
相关产品推荐
相关产品推荐

