Определение переменных внутри макроса

#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. Я тоже хотел иметь возможность определять переменные внутри макроса, приведенное выше позволяет мне делать это без необходимости удвоения $ , поскольку это действительно сбивает с толку, особенно с большими макросами, к которым я и направлялся. С этим. Я добавлю лучший пример.