Правила шаблона групповых шаблонов GNU Make

Я хочу написать что-то вроде regex:

SRC:="a.dat.1 a.dat.2"    
$(SRC): %.dat.%: (\\1).rlt.(\\2)    
      dat2rlt $^ [email protected]

чтобы a.dat.1 и a.dat.2 предоставили a.rlt.1 и a. rlt.2.

В GNU Make info page, он говорит, что "% можно использовать только один раз".

Есть ли какой-то трюк для достижения этого в GNU Make?

Ответ 1

Я боюсь, что вы пытаетесь сделать это не так, как вы это предлагаете, поскольку, как вы уже упоминаете, (GNU) делает только один стебель "%", см. 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 $$< [email protected]
endef

$(foreach src,$(SRC),$(eval $(call GEN_RULE,$(word 1,$(subst ., ,$(src))),$(word 3,$(subst ., ,$(src))))))

Ответ 2

Используя именованные переменные, мы можем написать более читаемый код (основываясь на ответе Пальяса):

letters:=a b c
numbers:=1 2 3 4

define GEN_RULE
$(letter).dat.$(number) : $(letter).rlt.$(number)
    ./rlt2dat $$< [email protected]
endef

$(foreach number,$(numbers), \
  $(foreach letter,$(letters), \
    $(eval $(GEN_RULE)) \
  ) \
)

Мы можем генерировать SRC аналогичным образом. Обратите внимание, что при использовании этого метода SRC будет содержать все комбинации. Это может или не может быть полезным.

Ответ 3

Для ограниченного примера, который вы дали, вы можете использовать шаблон с одним %.

SRC := a.dat.1 a.dat.2
${SRC}: a.dat.%: a.rlt.%    
      dat2rlt $^ [email protected]
  • $* в рецепте будет расширяться до того, что соответствует %.
  • Обратите внимание, что " вокруг вашего исходного макроса определенно неверно.
  • Взгляните на .SECONDEXPANSION в руководстве для более сложных вещей (или здесь).