带可选通配符依赖的Make目标在依赖更新时未触发更新求助
解决Makefile模式规则中可选通配符依赖的问题
要实现foo.docx依赖foo_*.csv(无CSV时仍可构建,且CSV更新时触发重新构建),核心是让Make在规则实例化阶段正确展开通配符,同时兼容依赖不存在的场景,以下是具体解决方案:
正确的Makefile写法
使用Make的**二次展开(SECONDEXPANSION)**特性,让依赖中的通配符在匹配到具体目标后再解析:
.SECONDEXPANSION: %.docx: %.md $$(wildcard $$*_*.csv) @echo building $@ @touch $@
代码说明
.SECONDEXPANSION::启用二次展开机制,依赖会被分两次解析。第一次解析时$$被替换为单个$,得到$(wildcard $*_*.csv);第二次解析时,$*会替换为当前目标的前缀(比如构建thing.docx时,$*就是thing),此时wildcard会实际查找所有thing_*.csv文件。- 若不存在对应前缀的CSV,
wildcard返回空值,规则仅依赖%.md,仍可正常构建;若存在CSV,它们会被加入依赖列表,文件更新时会触发目标重新构建。
原有方案失效原因
方案1的问题
tables = $(wildcard $*_*.csv) %.docx: %.md $(tables) @echo building $@ @touch $@
tables是递归展开变量,但Make读取Makefile时会优先解析变量,此时$*还未绑定具体目标值,导致wildcard返回空。虽第一次构建时可能临时展开变量,但后续检查中不会重新计算tables,因此CSV更新无法触发重构。
方案2的问题
%.docx: %.md %_*.csv @echo building $@ @touch $@
这里的%_*.csv被视为必须存在的依赖,若没有匹配的CSV文件,Make会判定找不到规则依赖,直接报错终止构建。
验证测试
- 无CSV文件时构建:
$ rm thing.docx thing_table.csv $ make thing.docx building thing.docx $ ls thing.docx thing.docx
- 有CSV文件时构建与更新:
$ touch thing_table.csv $ make thing.docx building thing.docx $ touch thing_table.csv $ make thing.docx building thing.docx
内容的提问来源于stack exchange,提问作者Luther Blissett
相关产品推荐
相关产品推荐

