Вам необходимо дважды экранировать практически все функции и переменные, когда вы используете eval
. В большинстве случаев единственные вещи, которые не должны быть дважды экранированы, - это аргументы функции (поскольку функция call
полностью их расширит). В этом случае вам технически не нужно ни дважды избегать join
, ни SRC_DIR
, но это упростит вам жизнь, если вы просто всегда будете дважды экранировать все переменные и функции при использовании eval
.
Причина, по которой вам нужны двойные побеги, заключается в том, что расширение происходит дважды при использовании eval
. Функция eval
сама выполняет расширение, а затем расширение выполняется снова , когда блок, наконец, анализируется как синтаксис make-файла (т.е. когда он фактически вычисляется).
Как вы написали, wildcard
вызывается для строкового литерала $( test_SRC_DIR)*.c
. Если вы хотите, вы можете убедиться в этом сами, заменив wildcard
на info
в вашей версии и посмотрите, что произойдет.
Вам нужно отложить фактический вызов wildcard
до второго раскрытия, чтобы его аргумент был результатом расширения $(test_SRC_DIR)
.
Попробуйте это:
SRC_DIR = ./src/
PROG_NAME = test
define PROGRAM_template
$(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/)
$(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c)
endef
$(eval $(call PROGRAM_template,$(PROG_NAME)))
all:
@echo $(test_SRC_DIR)
@echo $(test_SRC_FILES)
@echo $(wildcard $(test_SRC_DIR)*.c)
EDIT : После публикации я подумал, что лучше проверить его, чтобы убедиться, что он действительно работает. При этом я обнаружил еще одну проблему. Вы должны избегать ставить пробелы между запятой и аргументом при вызове функций. Это приводит к тому, что буквенный символ пробела предшествует аргументу, который передается функции, и приводит к непредвиденным результатам. Я удалил пробелы после запятых в вызовах функций в моей версии (хотя это не проблема для вызова join
, я удалил пробелы и там только потому, что это хорошая привычка, в которую можно попасть).