Подтвердить что ты не робот

Как я могу использовать макросы для создания нескольких целей/правил Makefile внутри foreach? Таинственное поведение

Я использую GNU make 3.81. Вот тестовый файл, который демонстрирует проблему:

define BOZO

a$(1): b c
    touch a$(1)

endef

$(foreach i,1 2 3,$(call BOZO,$(i)))

Идея здесь заключается в использовании шаблона макроса (BOZO) для генерации правил, которые следуют предсказуемому шаблону.

Проблема: когда я запускаю make на этом make файле, я получаю сообщение об ошибке:

Makefile.fake:10: *** multiple target patterns.  Stop.

(где строка 10 - это строка с foreach).

Теперь я знаю, что эта ошибка обычно указывает. Посмотрите, к чему эта строка расширяется, используя функцию info, чтобы отправить расширение в стандартное. Я меняю строку 10 следующим образом:

$(info $(foreach i,1 2 3,$(call BOZO,$(i))))

и я запускаю:

$ make -n

a1: b c
    touch a1

a2: b c
    touch a2

a3: b c
    touch a3

make: *** No targets.  Stop.

Обратите внимание, что сообщение "нет целей" ожидается, так как функция $(info...) оценивается как пустая, но вызывает make для печати сгенерированных правил.

Запустите эти правила, тогда мы будем?

$make -n > out.txt
make: *** No targets.  Stop.
$make -f out.txt a1 a2 a3
touch a1
touch a2
touch a3
$

Aaargh! Правила работают нормально. Итак... это ошибка в make или в моем понимании?

Один заключительный ключ, который может помочь диагностировать: если я изменил строку foreach на:

$(foreach i,1,$(call BOZO,$(i)))

(так что foreach имеет только одну итерацию)

а затем do

$make a1

Я получаю другую ошибку:

make: *** No rule to make target `a1'.  Stop.

Я не знаю, как "видеть" расширение $(foreach ), которое делает вид, кроме $(info ), и его вывод легален, поэтому я довольно сильно озадачен.

4b9b3361

Ответ 1

$(foreach i,1 2 3,$(eval $(call BOZO,$(i))))

функция eval сообщает Make для синтаксического анализа структур как синтаксиса makefile, "принять" их. Я не знаю, почему Make возражал против правил un-eval'd именно таким образом, но такого рода академические.

Ответ 2

Бета-ответ правильный, но я хотел бы обратиться к комментарию: "Я не уверен, почему Make Objected to un un-eval'd rules".

Причина, по которой правила un-eval'd не работают, заключается в том, что make файл, в конечном счете, основан на линии, и строки прерываются до того, как переменные расширены. Так что просто невозможно развернуть переменную, чтобы она превратилась в многострочный результат: даже если расширение содержит символы новой строки, все это рассматривает как одну "линию". Когда make заканчивает расширение цикла foreach и анализирует результаты, он в основном видит это:

a1: b c touch a1 a2: b c touch a2 a3: b c touch b3

поэтому вы получаете ошибку "множественные целевые шаблоны".

Причины eval позволяют повторно интерпретировать результат расширения с самого начала как полный фрагмент синтаксиса makefile, включая прерывание строк и т.д., и почему здесь работает многострочное расширение.

Ответ 3

после использования функции eval все же я столкнулся с проблемой остановки множества шаблонов. Я рекурсивно строю цель с помощью foreach, но я столкнулся с этой проблемой с несколькими задачами. при запуске make файла на 32-битной платформе окна (которые корректно работают для Linux-машины)

define BOZO
$(CWD)/$(1).o:$(CWD).$(1).def
endef
$(foreach target,$(basename $(list)),$(eval $(call BOZO,$(target))))

$(CWD)/%.def: a.out
   @echo building [email protected]
   a.out %.def

Что-то вроде этого. Можете ли вы предложить для этого...!

Ответ 4

Может быть, старый, но всегда актуальный. Нет необходимости делать этот макрос вообще.

Решение вашей проблемы - просто определить это правило:

a%: b c
    touch a%

Процент действует как подстановочный знак. Смотрите больше информации здесь: fooobar.com/info/146566/...