Как улучшить парадигму $ (call $ (eval $ (call))) в использовании Make? - PullRequest
0 голосов
/ 05 июня 2019

Я пишу общие make-файлы и функции для удобства пользователей, поэтому, естественно, они должны иметь максимально простой интерфейс.При определении функций я использую эту парадигму:

define FUNCTION
target: $1
endef

FUNCTION2 = $(eval $(call FUNCTION,$1))

Теперь вместо того, чтобы сказать им сделать это

$(eval $(call FUNCTION, аргумент ))

Я могу сказать имсделать это

$(call FUNCTION2, аргумент )

, что проще.

Это работало как заклинание, пока кто-то не решил использовать .EXPORT_ALL_VARIABLES, так что у нас общий код (SSCCE) выглядит следующим образом:

define FUNCTION
target: $1
endef

FUNCTION2 = $(eval $(call FUNCTION,$1))

.EXPORT_ALL_VARIABLES:

all:    
    echo OK

Теперь, когда вы make это, вы получите:

Makefile:5: *** prerequisites cannot be defined in recipes.  Stop.

Ну, я думаю, это потому, что подпроцесс echo рецепта оценивает "переменную" FUNCTION2, которая затем неожиданно помещает строку предварительных условий в рецепт.Или что-то типа того.

Итак, мой вопрос: кто виноват?

Моя парадигма неверна, и я не должен ее использовать, потому что пользователи тогда не могут использовать .EXPORT_ALL_VARIABLES?Если да, есть ли способ исправить ситуацию, чтобы пользователи все еще могли вызывать простой FUNCTION2?

Или .EXPORT_ALL_VARIABLES злая особенность и не должна использоваться?

Ответы [ 3 ]

1 голос
/ 06 июня 2019

Мое личное мнение таково, что .EXPORT_ALL_VARIABLES является злой функцией и не должна использоваться. Тем не менее, я думаю, что это стоит запроса на улучшение для GNU make: он не должен запускаться eval при расширении переменных для экспорта.

1 голос
/ 06 июня 2019

Используйте unexport FUNCTION FUNCTION2, чтобы избавиться от этой ошибки.

И все же я должен согласиться с @MadScientist, что .EXPORT_ALL_VARIABLES является злом.

Он принудительно выполняет расширение всерекурсивные переменные перед выполнением каждого рецепта , что может легко сломать любую сложную систему сборки.

IMO, может быть полезно иметь способ остановить любое расширение автоматически экспортируемых переменных.

Единственное утешение в том, что почти никто не использует эту вещь .EXPORT_ALL_VARIABLES.

0 голосов
/ 06 июня 2019

В моей нерекурсивной системе сборки prorab Я использую eval, но без call.

Я передаю параметры через this_ переменные с префиксом, что-то вроде этого:

include prorab.mk

this_name := myapp

this_cxxflags += -Wall
this_cxxflags += -DDEBUG
this_cflags += -Wall

this_ldlibs += -lpthread

this_srcs += main.cpp myapp.cpp legacy.c

$(eval $(prorab-build-app))

Итак, eval все еще там, но вставка переменной вместо call делает ее короче, и пользователю также не нужно запоминать, какой аргумент call означает что, потому что переменные this_ имеют описательные имена.

...