Это ошибка в GNU make `filter`? - PullRequest
2 голосов
/ 07 января 2020

У меня есть Makefile, который начинается так:

CORE_PATH:=$(filter %/makefile_ltlibs.inc,$(MAKEFILE_LIST))

foobar:
        @echo "MAKEFILE_LIST = \"$(MAKEFILE_LIST)\""
        @echo "filter = \"$(filter %/makefile_ltlibs.inc,$(MAKEFILE_LIST))\""
        @echo "CORE_PATH = \"$(CORE_PATH)\""

и когда я запускаю gmake foobar, я получаю следующий вывод:

MAKEFILE_LIST = " GNUmakefile ../../matrixssl.test/crypto/Makefile ../common.mk ../core/makefiles/detect-and-rules.mk ../../matrixssl.test/crypto/makefile.inc makefile ../../matrixssl.test/crypto/makefile_ltlibs.inc"
filter = "../../matrixssl.test/crypto/makefile_ltlibs.inc"
CORE_PATH = ""

Как это возможно, что CORE_PATH здесь пусто?!

РЕДАКТИРОВАТЬ:

Я превратил его в отдельный тестовый случай:

FILTER_LIST1 := " foo bar"
FILTER_LIST2 := " foo bar "

WORD11 := $(filter foo,$(FILTER_LIST1))
WORD12 := $(filter bar,$(FILTER_LIST1))

WORD13 := $(filter foo,"$(FILTER_LIST1) ")
WORD14 := $(filter bar,"$(FILTER_LIST1) ")

WORD21 := $(filter bar,$(FILTER_LIST2))

foobar:
        @echo "FILTER_LIST1 = \"$(FILTER_LIST1)\""
        @echo "FILTER_LIST2 = \"$(FILTER_LIST2)\""
        @echo "WORD11 = \"$(WORD11)\""
        @echo "WORD12 = \"$(WORD12)\""
        @echo "WORD13 = \"$(WORD13)\""
        @echo "WORD14 = \"$(WORD14)\""
        @echo "WORD21 = \"$(WORD21)\""

вывод

FILTER_LIST1 = " foo bar"
FILTER_LIST2 = " foo bar "
WORD11 = "foo"
WORD12 = ""
WORD13 = "foo"
WORD14 = ""
WORD21 = "bar"

Мой вывод таков: filter не работает для последней записи. Или я что-то не так делаю?

1 Ответ

3 голосов
/ 07 января 2020

Ваша проблема с MAKEFILE_LIST связана с тем, что эта переменная расширяется каждый раз, когда make обрабатывает директиву include. Теперь использование := для установки значения CORE_PATH говорит make о необходимости сразу же оценить выражение. Поскольку вы находитесь в начале вашего Makefile, на данный момент MAKEFILE_LIST содержит только Makefile (см. Пример, приведенный в описании переменной ), и фильтр возвращает пустое значение.

С другой стороны, рецепт оценивается после того, как Makefile был полностью проанализирован. Следовательно, у вас есть намного более длинная последовательность в MAKEFILE_LIST, и вы можете отфильтровать ее. Чтобы получить то же самое с CORE_PATH, определите это с CORE_PATH = .... В этом случае определение будет расширено только при использовании CORE_PATH, а не при его определении (для получения дополнительной информации об этих двух «разновидностях» переменных см. GNU Make manual ).

Относительно Ваше редактирование, как упомянул Врумфондель, FILTER_LIST1 состоит из 3 слов (вы можете увидеть это, выполнив $(words $(FILTER_LIST1)), ", foo и bar", ни одно из них не будет bar. Аналогично, FILTER_LIST2 имеет 4 слова, ", foo, bar и ", и bar можно найти в списке.

...