Pregunta ¿Cuál es la diferencia entre las asignaciones de variables de Makefile de GNU =,? =,: = Y + =?


¿Alguien puede dar una explicación clara de cómo la asignación de variables realmente funciona en Makefiles?

Cuál es la diferencia entre :

 VARIABLE = value
 VARIABLE ?= value
 VARIABLE := value
 VARIABLE += value

He leído el sección en el manual de GNU Make, pero aún no tiene sentido para mí.


610
2018-01-15 23:19


origen


Respuestas:


Conjunto perezoso

VARIABLE = value

Configuración normal de una variable: los valores dentro de ella se expanden recursivamente cuando se usa la variable, no cuando se declara

Set Inmediato

VARIABLE := value

Configuración de una variable con expansión simple de los valores internos: los valores dentro de ella se expanden en el momento de la declaración.

Establecer si falta

VARIABLE ?= value

Configuración de una variable solo si no tiene un valor

Adjuntar

VARIABLE += value

Agregar el valor suministrado al valor existente (o establecerlo en ese valor si la variable no existía)


831
2018-01-15 23:25



Utilizando = hace que a la variable se le asigne un valor. Si la variable ya tenía un valor, se reemplaza. Este valor se expandirá cuando se use. Por ejemplo:

HELLO = world
HELLO_WORLD = $(HELLO) world!

# This echoes "world world!"
echo $(HELLO_WORLD)

HELLO = hello

# This echoes "hello world!"
echo $(HELLO_WORLD)

Utilizando := es similar a usar =. Sin embargo, en lugar de expandir el valor cuando se usa, se expande durante la asignación. Por ejemplo:

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)

Utilizando ?= asigna un valor a la variable iff la variable no fue asignada previamente Si a la variable se le asignó previamente un valor en blanco (VAR=), todavía se considera establecido creo. De lo contrario, las funciones son exactamente como =.

Utilizando += es como usar =, pero en lugar de reemplazar el valor, el valor se agrega al actual, con un espacio intermedio. Si la variable se estableció previamente con :=, se expande creo. El valor resultante se expande cuando se usa creo. Por ejemplo:

HELLO_WORLD = hello
HELLO_WORLD += world!

# This echoes "hello world!"
echo $(HELLO_WORLD)

Si algo como HELLO_WORLD = $(HELLO_WORLD) world! se utilizaron, se produciría una recursión, lo que probablemente terminaría con la ejecución de su archivo Makefile. Si A := $(A) $(B) fueron utilizados, el resultado no sería exactamente el mismo que usar += porque B se expande con := mientras += no causaría B para ser expandido


216
2018-01-15 23:34



Te sugiero que hagas algunos experimentos usando "hacer". Aquí hay una demostración simple, que muestra la diferencia entre = y :=.

/* 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 huellas dactilares:

x - later
y - foo bar
a - later
b - later bar

Ver explicación más elaborada aquí


43
2017-12-23 14:43



Cuando usas VARIABLE = value, Si value es en realidad una referencia a otra variable, entonces el valor solo se determina cuando VARIABLE es usado. Esto se ilustra mejor con un ejemplo:

VAL = foo
VARIABLE = $(VAL)
VAL = bar

# VARIABLE and VAL will both evaluate to "bar"

Cuando usas VARIABLE := value, obtienes el valor de value  como es ahora. Por ejemplo:

VAL = foo
VARIABLE := $(VAL)
VAL = bar

# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"

Utilizando VARIABLE ?= val significa que solo establece el valor de VARIABLE  Si  VARIABLE no está establecido ya. Si no está configurado, la configuración del valor se difiere hasta VARIABLE se usa (como en el ejemplo 1).

VARIABLE += value solo anexa value a VARIABLE. El valor real de value se determina tal como estaba cuando se estableció inicialmente, utilizando cualquiera = o :=.


27
2018-01-15 23:26



En las respuestas anteriores, es importante entender lo que significa "los valores se expanden en el momento de la declaración / uso". Dando un valor como *.cno implica ninguna expansión. Solo cuando esta cadena es utilizada por un comando, tal vez desencadene algunos globbing. Del mismo modo, un valor como $(wildcard *.c) o $(shell ls *.c) no implica ninguna expansión y se evalúa completamente en el momento de la definición, incluso si utilizamos := en la definición de variable.

Pruebe el siguiente Makefile en el directorio donde tiene algunos archivos 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

Corriendo make activará una regla que crea un archivo C extra (vacío), llamado foo.c pero ninguna de las 6 variables tiene foo.c en su valor


5
2017-12-12 11:40