web-dev-qa-db-fra.com

Quelle est la différence entre les GNU assignations de variables de Makefile =,? =,: = Et + =?

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.

716
mmoris

Lazy Set

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

Ensemble immédiat

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.

Définir si absent

VARIABLE ?= value

Définition d'une variable uniquement si elle n'a pas de valeur

Ajouter

VARIABLE += value

Ajout de la valeur fournie à la valeur existante (ou définition de cette valeur si la variable n'existe pas)

955
Alnitak

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.

244
strager

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

Voir l'explication plus élaborée ici

55
nickand

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 valuetelle 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 VARIABLEifVARIABLE 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 :=.

31
mipadi

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.

6
phs