Странное поведение foreach определяемой пользователем функции в Makefiles

#foreach #makefile #user-defined-functions

#заранее #makefile создать файл #определяемые пользователем функции #foreach #makefile

Вопрос:

У меня есть следующий Makefile:

 X=a.jar b.jar c.jar
Y=/var/tmp/abc/a.jar /var/tmp/abc/b.jar /var/tmp/abc/c.jar

all: $(addprefix /var/tmp/abc/tmp/, $(X))

define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$(dst): $(src)
        @echo $$@
        @echo $$^
        @mkdir -p $$(dir $$@)
        @cp $$^ $$@
endef
$(foreach jar, $(X), $(eval $(call AddRule, $(jar), $(filter %$(jar), $(Y)))))
  

(/var/tmp/abc/{a, b, c}.jar существует)

В принципе, для каждого имени файла в $ X я хочу найти полный путь в $ Y и создать правило, которое копирует этот файл в /var/tmp / abc / tmp (я знаю, что есть гораздо более простой способ сделать это, но мой фактический Makefile сложнее и нуждается в подобной конструкции).

Когда я запускаю этот Makefile, я получаю следующий вывод:

 /var/tmp/abc/tmp/a.jar
/var/tmp/abc/a.jar
/var/tmp/abc/tmp/b.jar
/var/tmp/abc/b.jar
make: *** No rule to make target `/var/tmp/abc/tmp/c.jar', needed by `all'.  Stop.
  

Теперь «забавная» часть: если я добавлю следующую строку после объявления правила «все»:

 X =d
  

все три файла jar обработаны, ‘make’ ничего не упоминает о ‘d’ (даже если файл ‘d’ не существует), и запуск прошел успешно.

Таким образом, похоже, что цикл foreach не проходит последнюю итерацию (или, скорее всего, происходит что-то еще, что приводит к тем же результатам). Кто-нибудь знает, в чем проблема и как ее исправить?

Спасибо!

Ответ №1:

Плохая не только последняя итерация цикла. В основном call расширяется $(dst) до любого значения, которое оно имеет, при call вызове, а не при вычислении нового кода. Затем вычисляется новый код, а затем на следующей итерации определение расширяется — со значениями, которые были установлены в предыдущем блоке нового кода. Итак, вместо {a, b, c} он выдает { , a, b} (вам придется некоторое время смотреть на это, прежде чем это обретет смысл).

Решение: добавьте пару дополнительных $ s:

 define AddRule
dst=$1
src=$2
/var/tmp/abc/tmp/$$(dst): $$(src)
    ...
endef