我想写类似正则表达式的东西:
SRC:="a.dat.1 a.dat.2"
$(SRC): %.dat.%: (\\1).rlt.(\\2)
dat2rlt $^ $@
为了让 a.dat.1 和 a.dat.2 分别对应 a.rlt.1 和 a.rlt.2,有什么方法可以在GNU Make中做到“%只能使用一次”吗?
我想写类似正则表达式的东西:
SRC:="a.dat.1 a.dat.2"
$(SRC): %.dat.%: (\\1).rlt.(\\2)
dat2rlt $^ $@
为了让 a.dat.1 和 a.dat.2 分别对应 a.rlt.1 和 a.rlt.2,有什么方法可以在GNU Make中做到“%只能使用一次”吗?
很抱歉,您尝试以所建议的方式进行的操作是不可能的,因为-正如您已经提到的那样-(GNU) make仅允许一个单一的通配符'%', 请参见http://www.gnu.org/software/make/manual/make.html#Pattern-Rules:
模式规则看起来像普通规则,只是它的目标包含字符'%'(确切地说只有一个)。
如果没有它,创建这样的“多维”目标会很麻烦。
解决此问题的一种方法是在命令中重建依赖项的名称(而不是在依赖项列表中):
SRC := a.dat.1 a.dat.2
all : $(SRC:%=%.dat2rlt)
%.dat2rlt :
dat2rtl $(word 1,$(subst ., ,$*)).rlt.$(word 2,$(subst ., ,$*)) $*
当然,这样做会失去依赖性,一旦rlt被更新,它就不会重新构建。
我唯一能想到的解决方法是显式地生成规则:
SRC := a.dat.1 a.dat.2
all : $(SRC)
define GEN_RULE
$1.dat.$2 : $1.rlt.$2
dat2rtl $$< $$@
endef
$(foreach src,$(SRC),$(eval $(call GEN_RULE,$(word 1,$(subst ., ,$(src))),$(word 3,$(subst ., ,$(src))))))
letters:=a b c
numbers:=1 2 3 4
define GEN_RULE
$(letter).dat.$(number) : $(letter).rlt.$(number)
./rlt2dat $$< $$@
endef
$(foreach number,$(numbers), \
$(foreach letter,$(letters), \
$(eval $(GEN_RULE)) \
) \
)
SRC
。请注意,使用这种方法,SRC
将包含所有组合。这可能有利也可能无益。在 Erzsébet Frigó 的答案基础上,你可以选择:
像这样:
letters:=a b c
numbers:=1 2 3 4
define rlt2dat
${0}s::$(letter).dat.$(number)
$(letter).dat.$(number): $(letter).rlt.$(number)
./${0} $$< $$@
endef
$(foreach number,$(numbers), \
$(foreach letter,$(letters), \
$(eval $(call rlt2dat))))
您可以使用以下命令构建所有rlt2dat目标:
make rlt2dats
对于你提供的有限示例,你可以使用一个%
的模式。
SRC := a.dat.1 a.dat.2
${SRC}: a.dat.%: a.rlt.%
dat2rlt $^ $@
$*
将扩展为与%
匹配的任何内容。"
肯定是错误的。.SECONDEXPANSION
以获取更复杂的内容(或在这里)。