Qual é a diferença entre a atribuições de variáveis ??GNU Makefile =, =,:? = E + =?

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

  •  19-08-2019
  •  | 
  •  

Pergunta

Alguém pode dar uma explicação clara de como atribuição de variável realmente funciona em Makefiles.

O que é a diferença entre:

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

Eu li o seção no GNU make de manual, mas ele ainda não faz sentido para mim.

Foi útil?

Solução

preguiçoso Set

VARIABLE = value

A configuração normal de uma variável - valores dentro dele são expandidos de forma recursiva quando a variável é usada, não quando ele é declarado

Imediato Set

VARIABLE := value

Configuração de uma variável com simples expansão dos valores dentro -. Valores dentro dele são expandidas em tempo de declaração

Set Se Ausente

VARIABLE ?= value

Configuração de uma variável somente se ele não tem um valor

Anexar

VARIABLE += value

Acrescentando o valor fornecido para o valor existente (ou ajuste a esse valor se a variável não existia)

Outras dicas

Usando = faz com que a variável a ser atribuído um valor. Se a variável já tinha um valor, ele é substituído. Este valor será ampliada quando ele é 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)

Usando := é semelhante ao uso =. No entanto, em vez do valor que está sendo expandida quando ele é 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)

Usando ?= atribui à variável um valor sse a variável não foi atribuído anteriormente. Se a variável foi anteriormente atribuído um valor em branco (VAR=), ainda é considerado set Eu acho . Caso contrário, funciona exatamente como =.

Usando += é como usar =, mas em vez de substituir o valor, o valor é acrescentado ao atual, com um espaço entre elas. Se a variável foi definida anteriormente com :=, ele é expandido Eu acho . O valor resultante é expandido quando ele é usado Eu acho . Por exemplo:

HELLO_WORLD = hello
HELLO_WORLD += world!

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

Se foram usados ??algo como HELLO_WORLD = $(HELLO_WORLD) world!, recursão resultaria, que provavelmente terminará a execução de seu Makefile. Se foram utilizados A := $(A) $(B), o resultado não seria exatamente o mesmo que usar += porque B é expandido com := enquanto += que não causa B para ser expandido.

Eu sugiro que você faça algumas experiências usando "make". Aqui é um simples demo, 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

Verifique explicação mais elaborada aqui

Quando você usa VARIABLE = value, se value é realmente uma referência a outra variável, então o valor é determinada apenas quando VARIABLE é usado. Isto é melhor ilustrado com um exemplo:

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

# VARIABLE and VAL will both evaluate to "bar"

Quando você usa VARIABLE := value, você obter o valor de value como é agora . Por exemplo:

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

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

Usando meios VARIABLE ?= val que você só definir o valor da VARIABLE se VARIABLE ainda não estiver definido. Se ainda não estiver definido, a definição do valor é adiada até VARIABLE é utilizado (como no exemplo 1).

VARIABLE += value apenas acrescenta value para VARIABLE. O valor real de value é determinada como estava quando foi inicialmente definido, utilizando quer = ou :=.

Nas respostas acima, É importante compreender que se entende por "valores são expandidas em tempo de declaração / uso". Dando um valor como *.c não implica qualquer expansão. É somente quando este texto é utilizado por um comando que vai talvez provocar alguma englobamento. Da mesma forma, um valor como $(wildcard *.c) ou $(shell ls *.c) não implica qualquer expansão e está completamente avaliada em tempo de definição, mesmo que usado := na definição variável.

Tente o seguinte Makefile no diretório onde 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

Running make irá desencadear uma regra que cria um (Vazio) arquivo extra C, chamado foo.c mas nenhuma das 6 variáveis ??tem foo.c em seu valor.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top