С участием:
FILES = $(shell ls)
с таким отступом внизу all
, это команда сборки. Итак, это расширяется $(shell ls)
, а затем пытается выполнить команду FILES ...
.
Если FILES
предполагается, что это make
переменная, эти переменные должны быть назначены вне части рецепта, например:
FILES = $(shell ls)
all:
echo $(FILES)
Конечно, это означает, что FILES
он будет установлен на «вывод из ls
» перед запуском любой из команд, создающих файлы .tgz. (Хотя, как отмечает Каз, переменная каждый раз повторно расширяется, поэтому в конечном итоге она будет включать файлы .tgz; некоторые варианты make должны FILES := ...
избегать этого для эффективности и / или правильности. 1 )
Если FILES
предполагается, что это переменная оболочки, вы можете установить ее, но вам нужно сделать это в оболочке, без пробелов и в кавычках:
all:
FILES="$(shell ls)"
Однако каждая строка запускается отдельной оболочкой, поэтому эта переменная не сохранится до следующей строки, поэтому вы должны немедленно использовать ее:
FILES="$(shell ls)"; echo $$FILES
Это все немного глупо, поскольку оболочка будет расширяться *
(и другие выражения оболочки) в первую очередь за вас, поэтому вы можете просто:
echo *
как вашу команду оболочки.
Наконец, как общее правило (не совсем применимо к этому примеру): как отмечает эсперанто в комментариях, использование вывода из ls
не совсем надежно (некоторые детали зависят от имен файлов, а иногда даже от версии ls
; некоторые версии ls
попытки очистить вывод в некоторых случаях). Таким образом, как l0b0 и idelic примечание, если вы используете GNU make, вы можете использовать $(wildcard)
и $(subst ...)
выполнять все внутри make
себя (избегая проблем с «странными символами в имени файла»). (В sh
сценариях, в том числе в make-файлах с рецептами, можно использовать другой метод, find ... -print0 | xargs -0
чтобы избежать появления пробелов, символов новой строки, управляющих символов и т. Д.)
1 В документации GNU Make далее отмечается, что POSIX добавила ::=
присваивание в 2012 году . Я не нашел для этого краткую справочную ссылку на документ POSIX и не знаю, какие make
варианты поддерживают ::=
присваивание, хотя GNU make делает это сегодня с тем же значением, что и :=
, т. Е. Выполняет назначение прямо сейчас с расширением.
Обратите внимание, что VAR := $(shell command args...)
это также может быть записано VAR != command args...
в нескольких make
вариантах, включая все современные варианты GNU и BSD, насколько мне известно. У этих других вариантов нет, $(shell)
поэтому использование VAR != command args...
лучше в том, что они короче и работают в большем количестве вариантов.
ls
withsed
и cut), а затем использовать результаты в rsync и других командах. Должен ли я повторять длинную команду снова и снова? Нельзя ли сохранить результаты во внутренней переменной Make?FILE = $(shell ls *.c | sed -e "s^fun^bun^g")
make
может сделать это без использования оболочки:FILE = $(subst fun,bun,$(wildcard *.c))
.Кроме того, в дополнение к ответу Торека: одна вещь, которая выделяется, - это то, что вы используете лениво вычисляемое назначение макроса.
Если вы используете GNU Make, используйте
:=
присваивание вместо=
. Это назначение вызывает немедленное расширение правой части и сохранение ее в левой переменной.Если вы используете
=
присвоение, это означает, что каждое отдельное вхождение$(FILES)
будет расширять$(shell ...)
синтаксис и, таким образом, вызывать команду оболочки. Это замедлит выполнение вашей задачи make или даже приведет к неожиданным последствиям.источник
for x in $(FILES); do command $$x; done
. Обратите внимание на удвоение,$$
которое передает сингл$
в оболочку. Также фрагменты снаряда однострочны; для написания многострочного кода оболочки вы используете продолжение обратной косой черты, которое обрабатываетсяmake
само по себе и сворачивается в одну строку. Это означает, что точки с запятой, разделяющие команды оболочки, являются обязательными.