GNU Make的多通配符模式规则

her*_*xbd 17 design-patterns makefile gnu-make

我想写一些像正则表达式:

SRC:="a.dat.1 a.dat.2"    
$(SRC): %.dat.%: (\\1).rlt.(\\2)    
      dat2rlt $^ $@
Run Code Online (Sandbox Code Playgroud)

这样a.dat.1a.dat.2将给出a.rlt.1a.rlt.2.

在GNU Make info页面中,它显示"%只能使用一次".

在GNU Make中有一些技巧可以实现吗?

小智 12

我担心你想要做的事情不可能像你建议的那样,因为 - 正如你已经提到的那样 - (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 ., ,$*)) $*
Run Code Online (Sandbox Code Playgroud)

但是,当然,这种方式会丢失依赖关系,一旦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))))))
Run Code Online (Sandbox Code Playgroud)


小智 6

使用命名变量,我们可以编写更可读的代码(基于 Paljas 的回答):

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)) \
  ) \
)
Run Code Online (Sandbox Code Playgroud)

我们可以SRC用类似的方式生成。请注意,使用该方法SRC将包含所有组合。这可能有好处,也可能没有好处。