Odpowiedzi:
VARIABLE = value
Normalne ustawienie zmiennej, ale wszelkie inne zmienne wymienione w valuepolu 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. valuejest zawsze oceniany, kiedy VARIABLEjest 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ż Bjest rozszerzona o :=natomiast +=nie spowoduje Bzostać rozszerzony.
VARIABLE = literali VARIABLE := literalzawsze 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 valuetak naprawdę jest odwołaniem do innej zmiennej, to wartość jest określana tylko wtedy, gdy VARIABLEjest 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 ?= valoznacza, ż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 VARIABLEużycia (jak w przykładzie 1).
VARIABLE += valuepo prostu dołącza valuedo VARIABLE. Rzeczywista wartość valuejest 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 *.cnie 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 makeuruchomi regułę, która tworzy dodatkowy (pusty) plik C, wywoływany, foo.cale żadna z 6 zmiennych nie ma foo.cswojej wartości.