Odpowiedzi:
VARIABLE = value
Normalne ustawienie zmiennej, ale wszelkie inne zmienne wymienione w value
polu są rekurencyjnie rozszerzane o ich wartość w punkcie, w którym zmienna jest używana, a nie w tej, którą miała w momencie deklaracji
VARIABLE := value
Ustawienie zmiennej z prostym rozszerzaniem wartości wewnątrz - wartości w niej są rozszerzane w czasie deklaracji.
VARIABLE ?= value
Ustawienie zmiennej tylko wtedy, gdy nie ma wartości. value
jest zawsze oceniany, kiedy VARIABLE
jest dostępny. Jest to równoważne z
ifeq ($(origin FOO), undefined)
FOO = bar
endif
Więcej informacji znajduje się w dokumentacji .
VARIABLE += value
Dołączanie podanej wartości do wartości istniejącej (lub ustawienie tej wartości, jeśli zmienna nie istnieje)
Użycie =
powoduje przypisanie zmiennej wartości. Jeśli zmienna ma już wartość, jest zastępowana. Ta wartość zostanie rozszerzona, gdy zostanie użyta. Na przykład:
HELLO = world
HELLO_WORLD = $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# This echoes "hello world!"
echo $(HELLO_WORLD)
Korzystanie :=
jest podobne do korzystania =
. Jednak zamiast wartości, która jest używana, jest ona rozwijana podczas przypisywania. Na przykład:
HELLO = world
HELLO_WORLD := $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# Still echoes "world world!"
echo $(HELLO_WORLD)
HELLO_WORLD := $(HELLO) world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Użycie ?=
przypisuje zmiennej wartość, jeśli zmienna nie była wcześniej przypisana. Jeśli do tej zmiennej wcześniej przypisano pustą wartość ( VAR=
), myślę , że nadal jest uważana za zestaw . W przeciwnym razie działa dokładnie tak samo =
.
Używanie +=
jest jak używanie =
, ale zamiast zamiany wartości, wartość jest dołączana do bieżącej, z odstępem pomiędzy nimi. Jeśli zmienna była wcześniej ustawiona za pomocą :=
, to myślę , że jest rozwinięta . Otrzymana wartość jest rozszerzona, gdy jest używany myślę . Na przykład:
HELLO_WORLD = hello
HELLO_WORLD += world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Jeśli zostanie HELLO_WORLD = $(HELLO_WORLD) world!
użyte coś podobnego , nastąpi rekurencja, co najprawdopodobniej zakończy wykonanie pliku Makefile. Jeśli A := $(A) $(B)
użyto, wynik nie byłby dokładnie taki sam, jak przy użyciu +=
ponieważ B
jest rozszerzona o :=
natomiast +=
nie spowoduje B
zostać rozszerzony.
VARIABLE = literal
i VARIABLE := literal
zawsze jest równoważna. Czy dobrze to zrozumiałem?
Sugeruję wykonanie kilku eksperymentów z użyciem „make”. Oto proste demo pokazujące różnicę między =
i :=
.
/* Filename: Makefile*/
x := foo
y := $(x) bar
x := later
a = foo
b = $(a) bar
a = later
test:
@echo x - $(x)
@echo y - $(y)
@echo a - $(a)
@echo b - $(b)
make test
drukuje:
x - later
y - foo bar
a - later
b - later bar
@
przodu każdego przepisu, aby uniknąć mylącego powtarzania wyników.
/* ... */
komentowania bloków
Gdy używasz VARIABLE = value
, jeśli value
tak naprawdę jest odwołaniem do innej zmiennej, to wartość jest określana tylko wtedy, gdy VARIABLE
jest używana. Najlepiej ilustruje to przykład:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Kiedy używasz VARIABLE := value
, otrzymujesz wartość value
taką, jaka jest teraz . Na przykład:
VAL = foo
VARIABLE := $(VAL)
VAL = bar
# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Używanie VARIABLE ?= val
oznacza, że ustawiasz tylko wartość VARIABLE
if, która VARIABLE
nie jest już ustawiona. Jeśli nie jest jeszcze ustawiony, ustawienie wartości jest odraczane do momentu VARIABLE
użycia (jak w przykładzie 1).
VARIABLE += value
po prostu dołącza value
do VARIABLE
. Rzeczywista wartość value
jest ustalana w stanie, w jakim była początkowo ustawiona, przy użyciu albo =
lub :=
.
W powyższych odpowiedziach ważne jest, aby zrozumieć, co należy rozumieć przez „wartości są rozszerzane w czasie deklaracji / użytkowania”. Podanie wartości podobnej *.c
nie pociąga za sobą żadnego rozszerzenia. Tylko wtedy, gdy ten ciąg jest używany przez polecenie, może wywołać trochę globowania. Podobnie, wartość taka jak $(wildcard *.c)
lub $(shell ls *.c)
nie pociąga za sobą żadnego rozszerzenia i jest całkowicie oceniana w czasie definicji, nawet jeśli zastosowaliśmy ją :=
w definicji zmiennej.
Wypróbuj następujący Makefile w katalogu, w którym masz jakieś pliki C.
VAR1 = *.c
VAR2 := *.c
VAR3 = $(wildcard *.c)
VAR4 := $(wildcard *.c)
VAR5 = $(shell ls *.c)
VAR6 := $(shell ls *.c)
all :
touch foo.c
@echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
@echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
@echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
@echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
@echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
@echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
rm -v foo.c
Uruchomienie make
uruchomi regułę, która tworzy dodatkowy (pusty) plik C, wywoływany, foo.c
ale żadna z 6 zmiennych nie ma foo.c
swojej wartości.