Respostas:
VARIABLE = value
Configuração normal de uma variável, mas quaisquer outras variáveis mencionadas com o value
campo 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 B
expansão.
VARIABLE = literal
e VARIABLE := literal
sempre é 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 ?= val
significa 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 VARIABLE
seja usada (como no exemplo 1).
VARIABLE += value
apenas anexa value
a 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 *.c
nã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 make
acionará uma regra que cria um arquivo C extra (vazio), chamado, foo.c
mas nenhuma das 6 variáveis possui foo.c
seu valor.