create - makefile linux c
¿Cuál es la diferencia entre las asignaciones de variables Makefile de GNU=,?=,:=Y+=? (5)
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 una simple expansión de los valores internos: los valores dentro de ella 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
Adjuntar
VARIABLE += value
Anexando el valor suministrado al valor existente (o configurándolo a ese valor si la variable no existía)
¿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 la section en el manual de GNU Make, pero todavía no tiene sentido para mí.
Cuando usa VARIABLE = value
, si el value
es en realidad una referencia a otra variable, entonces el valor solo se determina cuando se usa VARIABLE
. Esto se ilustra mejor con un ejemplo:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Cuando usa 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á establecido, la configuración del valor se aplaza hasta que se usa VARIABLE
(como en el ejemplo 1).
VARIABLE += value
solo agrega value
a VARIABLE
. El valor real del value
se determina como estaba cuando se estableció 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 secuencia es utilizada por un comando que puede desencadenar algunos globos. De manera similar, 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 usamos :=
en la definición de la 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
La ejecución de make
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.
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)
make test
impresiones de make test
:
x - later
y - foo bar
a - later
b - later bar
Usar =
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 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)
Usando ?=
Asigna un valor a la variable si la variable no fue asignada previamente. Si a la variable se le asignó previamente un valor en blanco ( VAR=
), creo que todavía se considera un conjunto. 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 estableció previamente con :=
, creo que se expandió. 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 usaron, se produciría una recursión, lo que probablemente terminaría con la ejecución de su Makefile. Si se utilizara 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.