如何消除Makefile重复代码?实现多目标共享同一规则
简化你的Makefile,消除重复代码
要消除这些重复的规则,我们可以利用Makefile的静态模式规则和变量技巧,把重复的逻辑抽离出来,让所有生成目标共享同一套规则。
优化后的Makefile代码(直观版)
# 定义生成文件路径 ALLFILE = hosts/all.txt WESTFILE = hosts/west.txt EASTFILE = hosts/east.txt # 所有需要生成的文件列表 GENERATEDFILES = $(ALLFILE) $(WESTFILE) $(EASTFILE) # 给每个生成文件绑定对应的依赖源文件 $(ALLFILE): DEPENDS = $(filter-out $(GENERATEDFILES), $(wildcard hosts/*.txt)) $(WESTFILE): DEPENDS = hosts/oregon.txt hosts/washington.txt hosts/idaho.txt $(EASTFILE): DEPENDS = hosts/new_york.txt hosts/virginia.txt # 提取重复的头部注释为变量,后续修改只需要改这里 GENERATED_HEADER = '# DO NOT EDIT\n# Edit individual host/ files instead.\n# Regenerate with `make`.\n' # 统一构建规则:所有生成文件共用这一段逻辑 $(GENERATEDFILES): @printf '$(GENERATED_HEADER)' > $@ @echo '' >> $@ cat $(DEPENDS) >> $@ # 默认目标:执行make时自动生成所有文件 .DEFAULT_GOAL := all all: $(GENERATEDFILES)
关键优化点说明
抽离重复注释:把每个生成文件开头的固定注释做成
GENERATED_HEADER变量,避免重复写三遍相同的echo命令,后续要修改注释只需要改这一处。关联变量绑定依赖:通过
$(目标): DEPENDS = 依赖文件的方式,给每个生成目标单独绑定对应的源文件依赖,规则里直接用$(DEPENDS)引用,逻辑清晰易懂。统一规则体:所有生成文件的构建命令完全复用,彻底消除了重复的规则代码,后续新增生成文件时,只需要添加一行变量定义和依赖绑定即可。
另一种更灵活的写法(静态模式版)
如果后续要新增更多区域的生成文件,这种写法扩展性更好:
# 生成文件列表 GENERATEDFILES = hosts/all.txt hosts/west.txt hosts/east.txt # 定义每个生成文件对应的源文件(用目标的核心名称做变量后缀) ALL_SOURCES = $(filter-out $(GENERATEDFILES), $(wildcard hosts/*.txt)) WEST_SOURCES = hosts/oregon.txt hosts/washington.txt hosts/idaho.txt EAST_SOURCES = hosts/new_york.txt hosts/virginia.txt GENERATED_HEADER = '# DO NOT EDIT\n# Edit individual host/ files instead.\n# Regenerate with `make`.\n' # 静态模式规则:自动匹配所有hosts/xxx.txt格式的生成目标 $(GENERATEDFILES): hosts/%.txt: $($(subst hosts/,,$(basename $@))_SOURCES) @printf '$(GENERATED_HEADER)' > $@ @echo '' >> $@ cat $^ >> $@ .DEFAULT_GOAL := all all: $(GENERATEDFILES)
它通过$(subst hosts/,,$(basename $@))提取目标的核心名称(比如hosts/west.txt会被处理成west),自动对应到WEST_SOURCES变量获取依赖,新增生成文件时只需要加一行XXX_SOURCES定义即可。
内容的提问来源于stack exchange,提问作者Schwern
相关产品推荐
相关产品推荐

