Qualcuno può dare una chiara spiegazione di come l’assegnazione delle variabili funzioni davvero nei Makefile.
Qual è la differenza tra :
VARIABLE = value VARIABLE ?= value VARIABLE := value VARIABLE += value
Ho letto la sezione nel manuale di GNU Make, ma non ha ancora senso per me.
VARIABLE = value
Impostazione normale di una variabile: i valori al suo interno vengono espansi in modo ricorsivo quando viene utilizzata la variabile, non quando è dichiarata
VARIABLE := value
Impostazione di una variabile con semplice espansione dei valori all’interno – i valori al suo interno vengono espansi al momento della dichiarazione.
VARIABLE ?= value
Impostazione di una variabile solo se non ha un valore
VARIABLE += value
Aggiunta del valore fornito al valore esistente (o impostazione di quel valore se la variabile non esisteva)
L’utilizzo di =
fa assegnare alla variabile un valore. Se la variabile ha già un valore, viene sostituita. Questo valore verrà espanso quando viene utilizzato. Per esempio:
HELLO = world HELLO_WORLD = $(HELLO) world! # This echoes "world world!" echo $(HELLO_WORLD) HELLO = hello # This echoes "hello world!" echo $(HELLO_WORLD)
Usando :=
è simile all’utilizzo =
. Tuttavia, al posto del valore espanso quando viene utilizzato, viene espanso durante l’assegnazione. Per esempio:
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)
Utilizzando ?=
Assegna alla variabile un valore se la variabile non è stata assegnata in precedenza. Se alla variabile è stato assegnato in precedenza un valore vuoto ( VAR=
), è ancora considerato come impostato. Altrimenti, funziona esattamente come =
.
Usare +=
è come usare =
, ma invece di sostituire il valore, il valore viene aggiunto a quello corrente, con uno spazio intermedio. Se la variabile è stata precedentemente impostata con :=
, è espansa, penso . Il valore risultante viene espanso quando viene usato, penso . Per esempio:
HELLO_WORLD = hello HELLO_WORLD += world! # This echoes "hello world!" echo $(HELLO_WORLD)
Se qualcosa come HELLO_WORLD = $(HELLO_WORLD) world!
sono stati utilizzati, ne risulterebbe la ricorsione, che molto probabilmente finirebbe l’esecuzione del tuo Makefile. Se A := $(A) $(B)
sono stati usati, il risultato non sarebbe esattamente lo stesso di usare +=
perché B
è espanso con :=
mentre +=
non causerebbe l’espansione di B
Ti suggerisco di fare alcuni esperimenti usando “make”. Ecco una semplice demo, che mostra la differenza tra =
e :=
.
/* 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
stampe di make test
:
x - later y - foo bar a - later b - later bar
Controlla qui la spiegazione più dettagliata
Quando si utilizza VARIABLE = value
, se value
è effettivamente un riferimento a un’altra variabile, il valore viene determinato solo quando viene utilizzato VARIABLE
. Questo è meglio illustrato con un esempio:
VAL = foo VARIABLE = $(VAL) VAL = bar # VARIABLE and VAL will both evaluate to "bar"
Quando si utilizza VARIABLE := value
, si ottiene il valore del value
come è ora . Per esempio:
VAL = foo VARIABLE := $(VAL) VAL = bar # VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Usando VARIABLE ?= val
significa che si imposta solo il valore di VARIABLE
se VARIABLE
non è già impostato. Se non è già impostato, l’impostazione del valore viene differita fino a quando viene utilizzato VARIABLE
(come nell’esempio 1).
VARIABLE += value
aggiunge semplicemente value
a VARIABLE
. Il valore effettivo del value
è determinato com’era quando era stato inizialmente impostato, usando o =
o :=
.
Nelle risposte di cui sopra, è importante capire cosa si intende per “i valori vengono espansi alla dichiarazione / tempo di utilizzo”. Fornire un valore come *.c
non comporta alcuna espansione. È solo quando questa stringa viene usata da un comando che potrebbe innescare un po ‘di globbing. Allo stesso modo, un valore come $(wildcard *.c)
o $(shell ls *.c)
non comporta alcuna espansione ed è completamente valutato al momento della definizione anche se abbiamo usato :=
nella definizione della variabile.
Prova il seguente Makefile nella directory in cui hai alcuni file 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
L’esecuzione di make
attiverà una regola che crea un file C in più (vuoto), chiamato foo.c
ma nessuna delle 6 variabili ha foo.c
nel suo valore.