Z:
FILES = $(shell ls)
z takim wcięciem all
, jest to polecenie kompilacji. Więc to się rozwija $(shell ls)
, a następnie próbuje uruchomić polecenie FILES ...
.
Jeśli FILES
ma to być make
zmienna, zmienne te należy przypisać poza częścią receptury, np .:
FILES = $(shell ls)
all:
echo $(FILES)
Oczywiście oznacza to, że FILES
zostanie ustawiony na „wyjście z ls
” przed uruchomieniem któregokolwiek z poleceń tworzących pliki .tgz. (Chociaż, jak zauważa Kaz, zmienna jest ponownie rozszerzana za każdym razem, więc ostatecznie będzie zawierać pliki .tgz; niektóre warianty make muszą FILES := ...
tego unikać, ze względu na wydajność i / lub poprawność. 1 )
Jeśli FILES
ma to być zmienna powłoki, możesz ją ustawić, ale musisz to zrobić w shell-ese, bez spacji i zacytować:
all:
FILES="$(shell ls)"
Jednak każda linia jest prowadzona przez oddzielną powłokę, więc ta zmienna nie przetrwa do następnej linii, więc musisz ją natychmiast użyć:
FILES="$(shell ls)"; echo $$FILES
To wszystko jest trochę głupie, ponieważ powłoka będzie się rozszerzać *
(i inne wyrażenia glob powłoki) w pierwszej kolejności, więc możesz po prostu:
echo *
jako polecenie powłoki.
Na koniec, jako ogólna zasada (nie do końca dotyczy tego przykładu): jak zauważa esperanto w komentarzach, użycie danych wyjściowych z ls
nie jest całkowicie wiarygodne (niektóre szczegóły zależą od nazw plików, a czasem nawet wersji ls
; niektóre wersje ls
próby oczyszczenia wyjścia w niektórych przypadkach). Tak więc, jak l0b0 i ideliczna uwaga, jeśli używasz GNU, możesz użyć $(wildcard)
i $(subst ...)
osiągnąć wszystko w make
sobie (unikając problemów z "dziwnymi znakami w nazwie pliku"). (W sh
skryptach, w tym w plikach makefile z recepturami, inną metodą jest find ... -print0 | xargs -0
unikanie potknięcia się o spacje, znaki nowej linii, znaki sterujące itp.)
1 GNU Dokonywanie dokumentacji dalej zauważa, że POSIX wprowadza dodatkowe ::=
przypisanie w 2012 roku . Nie znalazłem szybkiego odnośnika do dokumentu POSIX dla tego, ani nie wiem od ręki, które make
warianty obsługują ::=
przypisywanie, chociaż GNU robi to dzisiaj, z tym samym znaczeniem, co :=
, tj. Wykonuje przypisanie teraz z rozszerzeniem.
Zauważ, że VAR := $(shell command args...)
można to również zapisać VAR != command args...
w kilku make
wariantach, w tym we wszystkich nowoczesnych wariantach GNU i BSD, o ile wiem. Te inne warianty nie mają, $(shell)
więc użycie VAR != command args...
jest lepsze zarówno pod względem krótszego, jak i pracy w większej liczbie wariantów.
ls
zsed
i wytnij), a następnie użyć wyników w rsync i innych poleceniach. Czy muszę w kółko powtarzać długie polecenie? Czy nie mogę przechowywać wyników w wewnętrznej zmiennej Make?FILE = $(shell ls *.c | sed -e "s^fun^bun^g")
make
może to zrobić bez użycia powłoki:FILE = $(subst fun,bun,$(wildcard *.c))
.Poza tym, oprócz odpowiedzi Torka: jedną rzeczą, która się wyróżnia, jest to, że używasz leniwie ocenianego przypisania makra.
Jeśli korzystasz z GNU Make, użyj
:=
przypisania zamiast=
. To przypisanie powoduje natychmiastowe rozwinięcie prawej strony i zapisanie w zmiennej po lewej stronie.Jeśli używasz
=
przypisania, oznacza to, że każde pojedyncze wystąpienie$(FILES)
będzie rozszerzać$(shell ...)
składnię, a tym samym wywoływać polecenie powłoki. Spowoduje to spowolnienie pracy, a nawet spowoduje zaskakujące konsekwencje.źródło
for x in $(FILES); do command $$x; done
. Zwróć uwagę na podwojenie,$$
które przekazuje jedynkę$
do powłoki. Również fragmenty muszli są jednowarstwowe; aby napisać wielowierszowy kod powłoki, należy użyć kontynuacji z ukośnikiem odwrotnym, która jest przetwarzanamake
samodzielnie i składana w jedną linię. Oznacza to, że średniki rozdzielające polecenia są obowiązkowe.