makefile: % шаблон в пререквизите $(переменная)

У меня что-то вроде этого работает:

target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23

$(myDir)target1.sfx : $(target1.PREREQUISITES)
    <same recipe here>

$(myDir)target2.sfx : $(target2.PREREQUISITES)
    <same recipe here>

и это то, что я хочу сделать, но это не работает:

target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23

$(myDir)%.sfx : $(%.PREREQUISITES)
    <commun recipe here>

Всегда говорится, что делать нечего, потому что цель актуальна.

У меня такое ощущение, что проблема может заключаться в том, что делается на каждом этапе сборки, я имею в виду, что делается в первую очередь% или $. Должно ли это работать просто отлично?

3 ответа

Решение

Спасибо user657267 за ваш ответ, он работает и дал мне хорошее преимущество. Для тех, кто не слишком знаком с, обратите внимание на двойной знак доллара. Однако я включаю свой ответ здесь, потому что он все еще использует % знак, который был частью моего первоначального вопроса и работает так же, как ваш. Я использую следующее решение.

.SECONDEXPANSION:

$(mydir)%.sfx: $$(%.PREREQUISITES)
    echo $^

Я только заметил и осознаю, что при использовании вторичного расширения make не сообщает вам, что у отсутствующей предпосылки нет правила, вместо этого он отображает вводящее в заблуждение сообщение о том, что правила для создания цели нет.

Для этого вам понадобится что-то вроде вторичного расширения, иначе расширение переменной в предварительных условиях происходит до замены шаблона, и вы не определили переменную с именем %.PREREQUISITES,

.SECONDEXPANSION:

$(mydir)%.sfx: $$($$*.PREREQUISITES)
    echo $^

Второе расширение, предложенное пользователем 657267, работает хорошо. GNU make также поддерживает своего рода механизм цикла, который вы можете использовать для создания нескольких правил с очень похожими формами:

target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2

# $(1) is a parameter to substitute. The $$ will expand as $.
define MY_rule
$$(myDir)$(1).sfx : $$($(1).PREREQUISITES)
    <same recipe here>
endef
$(foreach target,$(TARGETS),$(eval $(call MY_rule,$(target))))
  • foreach перебирает все слова в $(TARGETS) и назначает текущее слово $(target),
  • call выполняет расширение MY_rule где он заменяет $(1) с текущим значением $(target) а также $$ с $,
  • eval инстанцирует результат call расширение как обычное правило.

Результат первой итерации foreachНапример, будет:

$(eval $(call MY_rule,target1))

call будет оценивать как:

$(myDir)target1.sfx : $(target1.PREREQUISITES)
    <same recipe here>

а также eval будет создавать его как правило. Важно: не забывайте, что call выполняет первое расширение. Итак, если ваш <same recipe here> содержит $ символы, не забудьте удвоить их, если их расширение call Это хорошо. Если ваш рецепт использует переменные оболочки, даже возможно, что вы в конечном итоге с такими вещами, как $$$$var,

Этот механизм немного более мощный и общий, чем второе расширение. Он даже работает с более чем одним параметром для замены и с вложенными циклами:

target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir

# $(1): target
# $(2): directory
define MY_rule
$(2)$(1).sfx : $$($(1).PREREQUISITES)
    <same recipe here>
endef
$(foreach target,$(TARGETS),$(foreach dir,$(DIRS),$(eval $(call MY_rule,$(target),$(dir)))))

И вы даже можете вставить foreach-eval-call внутри define-endef:

target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir

# $(1): target
# $(2): directory
define MY_rule_1
$(2)$(1).sfx : $$($(1).PREREQUISITES)
    <same recipe here>
endef

# $(1): directory
define MY_rule_2
$$(foreach target,$$(TARGETS),$$(eval $$(call MY_rule_1,$$(target),$(1))))
endef
$(foreach dir,$(DIRS),$(eval $(call MY_rule_2,$(dir))))
Другие вопросы по тегам