правила шаблона с несколькими подстановочными знаками 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?


person heroxbd    schedule 19.09.2010    source источник
comment
Нет, этого не хватает. Обходной путь — динамически добавлять правила (с помощью eval или include). См., например. этот связанный вопрос или этот.   -  person reinierpost    schedule 19.09.2010


Ответы (3)


Я боюсь, что то, что вы пытаетесь сделать, невозможно сделать так, как вы предлагаете, поскольку, как вы уже упоминали, (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))))))
person Paljas    schedule 21.08.2015

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

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 будет содержать все комбинации. Это может быть или не быть полезным.

person Erzsébet Frigó    schedule 11.01.2019

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

SRC := a.dat.1 a.dat.2
${SRC}: a.dat.%: a.rlt.%    
      dat2rlt $^ $@
  1. $* в рецепте расширится до того, что соответствует %.
  2. Обратите внимание, что " вокруг вашего исходного макроса определенно неверны.
  3. Посмотрите .SECONDEXPANSION в руководстве для более сложных вещей (или здесь).
person bobbogo    schedule 01.10.2010
comment
извините, возможно, пример не исчерпывающий, но я хочу также охватить b.dat.1, b.dat.2. - person heroxbd; 27.06.2014