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

StackOverflow https://stackoverflow.com/questions/448910

  •  19-08-2019
  •  | 
  •  

Pregunta

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

¿Cuál es la diferencia entre:

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

He leído la sección en GNU Make's manual, pero todavía no tiene sentido para mí.

¿Fue útil?

Solución

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

Conjunto inmediato

VARIABLE := value

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

Establecer si está ausente

VARIABLE ?= value

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

Añadir

VARIABLE += value

Agregar el valor suministrado al valor existente (o establecer ese valor si la variable no existiera)

Otros consejos

El uso de = 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)

Usar := es similar a usar = . Sin embargo, en lugar de que el valor se expanda 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)

Usando ?= asigna a la variable un valor iff la variable no se asignó previamente. Si a la variable se le asignó previamente un valor en blanco ( VAR = ), todavía se considera establecida Creo . De lo contrario, funciona exactamente como = .

Usar += es como usar = , pero en lugar de reemplazar el valor, el valor se agrega al actual, con un espacio en el medio. Si la variable se configuró 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 se usara algo como HELLO_WORLD = $ (HELLO_WORLD) world! , se produciría una recursión, lo que probablemente terminaría con la ejecución de su Makefile. Si se usara A: = $ (A) $ (B) , el resultado no sería exactamente el mismo que usar + = porque B se expande con : = mientras que + = no causaría que B se expanda.

Te sugiero que hagas algunos experimentos usando "make". 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)

hacer prueba imprime:

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

Verifique una explicación más elaborada aquí

Cuando utiliza 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 utiliza VARIABLE: = value , obtiene el valor de value como está ahora . Por ejemplo:

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

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

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

VARIABLE + = value simplemente agrega value a VARIABLE . El valor real de value se determina como estaba cuando se configuró inicialmente, utilizando = o : = .

En las respuestas anteriores, es importante comprender qué se entiende por " los valores se expanden en el momento de la declaración / uso " ;. Dar un valor como * .c no implica ninguna expansión. Es solo cuando esta cadena es utilizada por un comando que tal vez desencadene un poco de bloqueo. Del mismo modo, un valor como $ (comodín * .c) o $ (shell ls * .c) no implica ninguna expansión y se evalúa por completo en el momento de la definición, incluso si : = usado 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

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top