Respostas:
VARIABLE = value
Configuração normal de uma variável, mas quaisquer outras variáveis mencionadas com o valuecampo são recursivamente expandidas com seu valor no ponto em que a variável é usada, não a que tinha quando foi declarada
VARIABLE := value
Configuração de uma variável com expansão simples dos valores internos - os valores dentro dela são expandidos no momento da declaração.
VARIABLE ?= value
Configuração de uma variável apenas se ela não tiver um valor. valueé sempre avaliado quando VARIABLEé acessado. É equivalente a
ifeq ($(origin FOO), undefined)
FOO = bar
endif
Veja a documentação para mais detalhes.
VARIABLE += value
Anexando o valor fornecido ao valor existente (ou definindo esse valor se a variável não existir)
O uso =faz com que seja atribuído um valor à variável. Se a variável já tiver um valor, ela será substituída. Este valor será expandido quando usado. Por exemplo:
HELLO = world
HELLO_WORLD = $(HELLO) world!
# This echoes "world world!"
echo $(HELLO_WORLD)
HELLO = hello
# This echoes "hello world!"
echo $(HELLO_WORLD)
Usar :=é semelhante a usar =. No entanto, em vez de o valor ser expandido quando usado, ele é expandido durante a atribuição. Por exemplo:
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)
O uso ?=atribui à variável um valor se a variável não foi atribuída anteriormente. Se a variável tiver sido atribuída anteriormente a um valor em branco ( VAR=), ainda será considerado definido, eu acho . Caso contrário, funciona exatamente como =.
Usar +=é como usar =, mas, em vez de substituir o valor, ele é anexado ao atual, com um espaço no meio. Se a variável foi definida anteriormente :=, é expandida, eu acho . O valor resultante é expandido quando usado, eu acho . Por exemplo:
HELLO_WORLD = hello
HELLO_WORLD += world!
# This echoes "hello world!"
echo $(HELLO_WORLD)
Se algo como HELLO_WORLD = $(HELLO_WORLD) world!fosse usado, resultaria em recursão, o que provavelmente terminaria a execução do seu Makefile. Se A := $(A) $(B)fosse usado, o resultado não seria exatamente o mesmo que usar, +=porque Bé expandido com :=enquanto +=não causaria Bexpansão.
VARIABLE = literale VARIABLE := literalsempre é equivalente. Eu entendi direito?
Eu sugiro que você faça alguns experimentos usando "make". Aqui está uma demonstração simples, mostrando a diferença entre =e :=.
/* 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 impressões:
x - later
y - foo bar
a - later
b - later bar
@na frente de cada receita para evitar essa repetição confusa de resultados.
/* ... */bloco de comentário
Quando você usa VARIABLE = value, se valueé realmente uma referência a outra variável, o valor é determinado apenas quando VARIABLEé usado. Isso é melhor ilustrado com um exemplo:
VAL = foo
VARIABLE = $(VAL)
VAL = bar
# VARIABLE and VAL will both evaluate to "bar"
Quando você usa VARIABLE := value, obtém o valor value como é agora . Por exemplo:
VAL = foo
VARIABLE := $(VAL)
VAL = bar
# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
Usar VARIABLE ?= valsignifica que você define apenas o valor de VARIABLE se VARIABLE ainda não estiver definido. Se ainda não estiver definido, a configuração do valor será adiada até que VARIABLEseja usada (como no exemplo 1).
VARIABLE += valueapenas anexa valuea VARIABLE. O valor real de valueé determinado como era quando foi definido inicialmente, usando =ou :=.
Nas respostas acima, é importante entender o que se entende por "valores expandidos no momento da declaração / uso". Dar um valor semelhante *.cnão implica nenhuma expansão. Somente quando essa string é usada por um comando é que talvez acione alguns globbing. Da mesma forma, um valor como $(wildcard *.c)ou $(shell ls *.c)não implica em nenhuma expansão e é completamente avaliado no momento da definição, mesmo que tenhamos usado :=na definição da variável.
Experimente o seguinte Makefile no diretório em que você tem alguns arquivos 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
A execução makeacionará uma regra que cria um arquivo C extra (vazio), chamado, foo.cmas nenhuma das 6 variáveis possui foo.cseu valor.