Quelqu'un peut-il expliquer clairement le fonctionnement réel des assignations de variables dans les Makefiles?.
Quelle est la différence entre :
VARIABLE = value
VARIABLE ?= value
VARIABLE := value
VARIABLE += value
J'ai lu le section dans GNU Manuel de Make, mais cela n'a toujours aucun sens pour moi.
VARIABLE = value
Paramétrage normal d'une variable - les valeurs qu'il contient sont développées de manière récursive lorsque la variable est utilisée, et non lorsqu'elle est déclarée
VARIABLE := value
Définition d’une variable avec une simple expansion des valeurs internes - les valeurs qu’elle contient sont développées au moment de la déclaration.
VARIABLE ?= value
Définition d'une variable uniquement si elle n'a pas de valeur
VARIABLE += value
Ajout de la valeur fournie à la valeur existante (ou définition de cette valeur si la variable n'existe pas)
L'utilisation de =
permet d'attribuer une valeur à la variable. Si la variable avait déjà une valeur, elle est remplacée. Cette valeur sera étendue lorsqu’elle sera utilisée. Par exemple:
_HELLO = world
HELLO_WORLD = $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# This echoes "hello world!"
echo $(HELLO_WORLD)
_
L'utilisation de :=
revient à utiliser _=
_. Toutefois, au lieu que la valeur soit développée lors de son utilisation, elle est développée lors de l'affectation. Par exemple:
_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)
_
Utiliser ?=
attribue à la variable une valeur si et seulement la variable n'avait pas encore été affectée. Si une valeur vide a déjà été attribuée à la variable (_VAR=
_), elle est toujours considérée comme définie je pense . Sinon, fonctionne exactement comme _=
_.
Utiliser +=
revient à utiliser _=
_, mais au lieu de remplacer la valeur, la valeur est ajoutée à la valeur actuelle, avec un espace entre les deux. Si la variable était précédemment définie avec _:=
_, elle est développée je pense . La valeur résultante est développée quand elle est utilisée je pense . Par exemple:
_HELLO_WORLD = hello
HELLO_WORLD += world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
_
Si quelque chose comme HELLO_WORLD = $(HELLO_WORLD) world!
était utilisé, il en résulterait une récursion qui mettrait probablement fin à l'exécution de votre Makefile. Si A := $(A) $(B)
était utilisé, le résultat ne serait pas exactement le même que si vous utilisiez _+=
_ car B
est développé avec _:=
_ alors que _+=
_ ne causera pas B
à développer.
Je vous suggère de faire des expériences en utilisant "make". Voici une simple démonstration montrant la différence entre =
et :=
.
/* 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
imprime:
x - later
y - foo bar
a - later
b - later bar
Lorsque vous utilisez VARIABLE = value
, si value
est en réalité une référence à une autre variable, la valeur n'est déterminée que lorsque VARIABLE
est utilisé. Ceci est mieux illustré par un exemple:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Lorsque vous utilisez VARIABLE := value
, vous obtenez la valeur de value
telle qu'elle est maintenant. Par exemple:
VAL = foo
VARIABLE := $(VAL)
VAL = bar
# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Utiliser VARIABLE ?= val
signifie que vous ne définissez que la valeur de VARIABLE
ifVARIABLE
n'est pas déjà défini. S'il n'est pas déjà défini, le réglage de la valeur est différé jusqu'à ce que VARIABLE
soit utilisé (comme dans l'exemple 1).
VARIABLE += value
ajoute simplement value
à VARIABLE
. La valeur réelle de value
est déterminée telle qu'elle était lors de son paramétrage initial, à l'aide de =
ou de :=
.
Dans les réponses ci-dessus, il est important de comprendre ce que l'on entend par "les valeurs sont étendues au moment de la déclaration/de l'utilisation". Donner une valeur telle que *.c
n'entraîne aucune expansion. Ce n'est que lorsque cette chaîne est utilisée par une commande qu'elle déclenchera peut-être un déplacement. De même, une valeur telle que $(wildcard *.c)
ou $(Shell ls *.c)
n'entraîne aucune expansion et est complètement évaluée au moment de la définition, même si nous avons utilisé :=
dans la définition de la variable.
Essayez le Makefile suivant dans le répertoire où vous avez des fichiers 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'exécution de make
déclenchera une règle qui crée un fichier C supplémentaire (vide), appelé foo.c
, mais aucune des 6 variables n'a foo.c
dans sa valeur.