You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make:在依赖列表中结合匹配模式使用文本函数的问题

问题根源

Makefile在解析阶段就会处理模式规则的依赖列表,此时$*还没有绑定具体的目标(比如build/x里的x),所以$(filter %/$*,$(list_of_files))中的$*是空字符串,筛选结果为空,自然不会触发任何依赖。

解决方案

有两种常用的解决方式:

方式一:使用二次展开(.SECONDEXPANSION)

通过.SECONDEXPANSION告诉Makefile,将规则的依赖延迟到匹配到具体目标后再展开,此时$*会被替换为目标对应的模式匹配部分。

修改后的Makefile:

list_of_files=a/x b/x a/y b/y c/z 

%:
    echo 0 $@
    touch $@

# 启用二次展开
.SECONDEXPANSION:
# 用$$*转义,二次展开时会替换为实际的$*值
build/%: $$(filter %/$$*,$(list_of_files))
    echo 1 target $@
    echo 1 prereq $?
    touch $@

.PHONY: all
all: build/x
    echo 

运行make all时,Makefile会先匹配到build/x,此时$$*展开为x,$(filter %/x,$(list_of_files))会筛选出a/x和b/x,触发这两个依赖的构建,再执行build/x的规则。

方式二:使用静态模式规则

如果能提前确定所有需要构建的build/%目标,可以用静态模式规则,明确列出目标集合,让$*在解析阶段就能绑定到具体的文件名。

修改后的Makefile:

list_of_files=a/x b/x a/y b/y c/z 
# 从list_of_files中提取唯一的文件名,生成build/xxx目标集合
build_targets := $(addprefix build/,$(sort $(notdir $(list_of_files))))

%:
    echo 0 $@
    touch $@

# 静态模式规则:针对每个build_targets,匹配%为文件名部分
$(build_targets): build/%: $(filter %/$*,$(list_of_files))
    echo 1 target $@
    echo 1 prereq $?
    touch $@

.PHONY: all
all: build/x
    echo 

这里build_targets会生成build/x build/y build/z,静态模式规则中的$*会对应每个目标的文件名部分(比如build/x对应x),解析阶段就能正确筛选出对应的依赖文件。

验证效果

运行make all后,会先执行a/x和b/x的构建(触发第一个%规则),然后执行build/x的规则,输出类似:

echo 0 a/x
0 a/x
touch a/x
echo 0 b/x
0 b/x
touch b/x
echo 1 target build/x
1 target build/x
echo 1 prereq a/x b/x
1 prereq a/x b/x
touch build/x
echo 

内容的提问来源于stack exchange,提问作者111111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:35:38