Посмотрел твой шлейф... цитируется здесь:
.PHONY: test
test:
@$(eval export files = $(shell ls))
for f in $(files) ; do \
t = $(ls | grep $$f) ; \
echo $$t;\
done
Итак... $(eval... )
запускает команду make.
$(shell ls)
запускает команду ls
в оболочке и подменяет ее вывод.
Таким образом, команда, запускаемая $(eval... )
, похожа на export files = file file2 makefile source.c
. Эта команда создает переменную make с именем files и экспортирует ее в дочерние make. Таким образом, экспорт, вероятно, не нужен.
Целиком $(eval... )
, вероятно, можно было бы заменить на files = $(wildcard *)
И, возможно, использовать :=
и поместить вне правила.
Цикл for
, состоящий из четырех строк, выполняется в оболочке. Первое, что делается, это подстановка переменных и функций make. Странным является $(ls | grep $$f)
. Поскольку ls не является функцией make, она попытается расширить переменную, которая не определена. Это пустая строка. Если это должен был быть оператор оболочки $(...)
, вам нужно удвоить $. $$
расширяется до $
. $(files)
расширен на основе eval.
Это становится (с использованием моего предыдущего примера):
for f in file file2 makefile source.c ; do
t =
echo $t;
done
На первый взгляд может показаться, что это четыре пустые строки, но нет. Команда t =
фактически запускает программу t
и передает знак равенства в качестве аргумента. t
скорее всего не существует. Таким образом, мы получаем четыре ошибки о том, что t не является корректной программой, за каждой из которых следует пустая строка (, если только t не определена в другом месте ).
Что-то более близкое к тому, что вы хотели:
files := $(wildcard *)
.PHONY: test
test:
for f in $(files) ; do \
t=$$(ls | grep $$f) ; \
echo $$t ; \
done
Будет выведено:
file file2
file2
makefile
source.c
Обратите внимание, что в первой строке перечислены два файла, так как в именах обоих есть слово «файл». Если это не то, что вы хотите, вы можете рассмотреть:
files := $(wildcard *)
.PHONY: test
test:
for f in $(files) ; do \
echo $$f ; \
done
или даже (могут быть специфичными для GNU make):
files := $(wildcard *)
.PHONY: test
test:
$(foreach f, $(files), echo $f ; )
Внутри рецепта make target команды обрабатываются иначе (путем порождения оболочки ), чем логика вне рецепта.
Вы можете переместить переменную за пределы рецепта:
.PHONY: test
foo := $(shell ls | grep makefile)
test:
echo $(foo)
или, благодаря этому вопросу , используйте eval:
.PHONY: test
test:
$(eval foo=$(shell ls | grep makefile))
echo $(foo)
Оба выводят следующее:
echo makefile
makefile