#macros #makefile
#макросы #makefile
Вопрос:
Как вы определяете переменную внутри макроса GNU make? Я использую GNU Make 4.0, и всякий раз, когда я выполняю присваивание, переменная пуста:
define TEST_MACRO
$(info $(1))
test_var := $(1)
$(info $(test_var))
endef
$(call TEST_MACRO,test)
Выводит:
test
(blank line)
Я пытался использовать рекурсивное расширение для назначения, но получаю те же результаты.
Ответ №1:
Вы не упомянули, какую версию Make вы используете, и между версиями есть тонкие различия в обработке макросов. Но у меня это работает (с использованием GNUmake 3.81):
define TEST_MACRO
$(info A $(1))
test_var := $(1)
$$(info B $$(test_var))
endef
$(eval $(call TEST_MACRO,test))
Комментарии:
1. Я использую GNU Make 4.0, я обновил вопрос этой информацией.
2. Я попробовал это, и это работает, не могли бы вы немного объяснить, почему я должен экранировать и оценивать все, что напрямую не использует аргументы?
3. @Lerp: Мне неприятно это признавать, но я на самом деле не уверен, зачем эти вещи необходимы; они просто работают.
4. Причина, по которой это должно быть так, заключается в том, что значение будет расширено дважды с помощью make. Сначала
$(call ...)
функция будет расширенаTEST_MACRO
. Затем$(eval ...)
функция развернет результат$(call ...)
функции. Вы можете немного узнать об этом, заменивeval
функцию наinfo
. Это покажет вам результат работыcall
функции, котораяeval
будет вычислять. Попробуйте оба способа и увидите разницу. Без дополнительного экранированияinfo
функции расширяются наcall
, перед установкой переменной наeval
.5. @MadScientist: Это имеет такой прекрасный смысл, что я не могу понять, как я не мог этого понять.
Ответ №2:
В конечном итоге я выбрал что-то вроде этого, поскольку чувствовал, что double $
был беспорядочным.
define TEST_MACRO
$(info B $(test_var))
endef
# Note test_var was defined after TEST_MACRO
test_var := test
$(eval $(value TEST_MACRO))
Недостатком этого является то, что вы не можете установить $1..$n
переменные, но это проще для чтения.
Редактировать — Лучший пример определения переменной внутри макроса. Приведенный выше пример демонстрировал, как вы будете передавать значения в макрос, например, с call
define TEST_MACRO
test_var := test
$(info B $(test_var))
endef
Комментарии:
1. Я не понимаю. Ваш первоначальный запрос состоял в том, чтобы определить переменную внутри макроса: это даже близко не подходит к выполнению этого?! Я предполагаю, что вы пропустили
$
предыдущее(value ...
, но даже в этом случае это просто запутанный способ записи$(info B $(test_var))
… зачем беспокоиться оeval
иvalue
?2. Я тоже хотел иметь возможность определять переменные внутри макроса, приведенное выше позволяет мне делать это без необходимости удвоения
$
, поскольку это действительно сбивает с толку, особенно с большими макросами, к которым я и направлялся. С этим. Я добавлю лучший пример.