Странный foreach + поведение пользовательских функций в Makefiles - PullRequest
1 голос
/ 12 ноября 2011

У меня есть следующий 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 Ответ

2 голосов
/ 12 ноября 2011

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

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

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