Определение пользовательских функций GNU make
В чем проблема с функцией dep2 в приведенном ниже примере кода?
dep1 = $(eval makefile_list_$1 := $(MAKEFILE_LIST))$(eval -include $1.mk)$(eval MAKEFILE_LIST := $(makefile_list_$1))
define dep2
$(eval makefile_list_$1 := $(MAKEFILE_LIST))
$(eval -include $1.mk)
$(eval MAKEFILE_LIST := $(makefile_list_$1))
endef
$(call dep1,test)
$(call dep2,test)
.DEFAULT_TARGET: all
.PHONY: all
all:
@echo [email protected]
GNU make 3.81 и 3.82 производят Makefile:10: *** missing separator. Stop.
, который указывает на вызов dep2, dep1 запускается без ошибок. Единственная разница между этими двумя вариантами - это новые строки в dep2 (и весь смысл, почему я хотел бы использовать define).
Ответы
Ответ 1
Вы забыли =
:
define dep2 =
Забастовкa >
EDIT:
Поместите точку с запятой в конце каждой строки. Я тестировал это, и он работает (в GNUMake 3.81).
define dep2
$(eval makefile_list_$1 := $(MAKEFILE_LIST));
$(eval -include $1.mk);
$(eval MAKEFILE_LIST := $(makefile_list_$1));
endef
Почему эти точки с запятой необходимы, я не знаю, но в документации define
, по-видимому, используется для многострочных "переменных" только при определении последовательностей команд оболочки, которые будут использоваться в рецептах, а не в командах, поэтому возможно, правила немного отличаются.
Ответ 2
Я бы переместил вызовы $(eval ...)
вне dep2
. Делая это таким образом, нет необходимости в точках с запятой в dep2
. Это означает удвоение признаков $
некоторых расширений, чтобы избежать расширения, которое делается слишком рано. Итак:
define dep2
makefile_list_$1 := $$(MAKEFILE_LIST)
-include $1.mk
MAKEFILE_LIST := $$(makefile_list_$1)
endef
$(eval $(call dep2,test))
# Quick checks for testing, to be removed from the final code...
$(info $(makefile_list_test))
$(info $(MAKEFILE_LIST))
.DEFAULT_TARGET: all
.PHONY: all
all:
@echo [email protected]
Я тестировал код выше, и он работает с Gnu Make 4.0. Я ожидаю, что он вернется к Gnu Make 3.8x. Шаблон $(eval $(call ...))
- это то, что я всегда делаю, чтобы выполнять свои пользовательские функции, и я использовал его довольно долгое время.
Ответ 3
В том, что вы делаете, многое можно улучшить. С одной стороны, вы действительно хотите включить eval-вызовы в один звонок наверху.
Ваша конкретная проблема, однако, проистекает из того, что не понимает, что многострочная рекурсивная строка, используемая командой make define, никогда не включает новую леди. Наиболее естественным для написания функций является
определить Foo
Линия 1
Line2
endef
Вы можете посмотреть, что строка eval видит и видит, что это делает с помощью команды info, например.
$ (информация $(вызов Foo, x) $(вызов Foo, y)).