GNU Makefile 변수 할당 =,? =, : = 및 + =의 차이점은 무엇입니까?


764

누구나 Makefile에서 변수 할당이 실제로 어떻게 작동하는지 명확하게 설명 할 수 있습니까?

차이점은 무엇입니까?

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

GNU Make 매뉴얼 의 섹션 을 읽었 지만 여전히 이해가되지 않습니다.

답변:


1028

게으른 세트

VARIABLE = value

변수의 일반 설정이지만 value필드에 언급 된 다른 변수 는 변수가 선언 된 시점이 아니라 변수가 사용 된 시점의 값으로 재귀 적으로 확장됩니다.

즉시 세트

VARIABLE := value

내부의 값을 간단하게 확장하여 변수 설정-변수 내의 값은 선언시 확장됩니다.

없는 경우 게으른 세트

VARIABLE ?= value

값이없는 경우에만 변수 설정 액세스 할 value때 항상 평가됩니다 VARIABLE. 그것은

ifeq ($(origin FOO), undefined)
  FOO = bar
endif

자세한 내용은 설명서 를 참조하십시오.

추가

VARIABLE += value

제공된 값을 기존 값에 추가 (또는 변수가없는 경우 해당 값으로 설정)


25
A + = B가 B를 확장합니까? 만약 내가 A + = B를하고 B + = C를한다면, A는 $ {B}와 $ {C}의 연결로 평가됩니까?
Anton Daneyko 2012

15
설명서의 링크 된 섹션에 나와 있습니다. + =는 원래 할당이 가진 단순하거나 재귀 적 의미에 따라 작동합니다. 그렇습니다. RHS를 확장 할 것이지만 그것이 즉시 또는 지연된 방식으로 수행되는지 여부는 LHS의 변수 유형에 따라 다릅니다.
Etan Reisner 2016 년

6
변수 값이 확장되었다는 것은 무엇을 의미합니까?
Sashko Lykhenko

2
@ СашкоЛихенко 확장의 의미를 얻으려면 여기를 살펴보십시오. gnu.org/software/make/manual/make.html#Flavors
Umair R

7
"없는 경우 설정"게으른 또는 즉시? "결석이 없을 경우 게으른 설정"및 "결석이없는 경우 즉시 설정"할 수 있습니까?
Woodrow Barlow

268

를 사용 =하면 변수에 값이 할당됩니다. 변수에 이미 값이 있으면 대체됩니다. 이 값은 사용될 때 확장됩니다. 예를 들면 다음과 같습니다.

HELLO = world
HELLO_WORLD = $(HELLO) world!

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

HELLO = hello

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

사용 :=은을 사용하는 것과 유사합니다 =. 그러나 값을 사용할 때 확장되는 대신 할당 중에 값이 확장됩니다. 예를 들면 다음과 같습니다.

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)

를 사용 하면 변수가 이전에 할당되지 않은 경우?= 변수에 값 이 할당됩니다. 변수가 이전에 빈 값을 (할당 된 경우 ), 그것은 여전히 세트로 간주됩니다 내 생각을 . 그렇지 않으면 정확히 같은 기능을합니다 .VAR==

사용 +=은을 사용 하는 것과 비슷 =하지만 값을 바꾸는 대신 값이 현재 값에 추가되고 사이에 공백이 추가됩니다. 변수가 이전에 설정 한 경우 :=, 확장 나는 생각한다 . 생각할 때 결과 값이 확장됩니다 . 예를 들면 다음과 같습니다.

HELLO_WORLD = hello
HELLO_WORLD += world!

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

같은 HELLO_WORLD = $(HELLO_WORLD) world!것이 사용되면 재귀가 발생하여 Makefile 실행이 종료 될 수 있습니다. 경우 A := $(A) $(B)사용 된 결과는 사용하는 것과 동일한되지 않을 것 +=때문 B으로 전개되고있는 :=반면 +=발생하지 것이다 B확장 할 수 있습니다.


3
그 결과는 그러므로 VARIABLE = literalVARIABLE := literal항상 동일합니다. 내가 알았어?
aiao

1
@aiao, 그렇습니다. 리터럴은 용도에 따라 다릅니다.
Sebastian

미묘한 차이점은 다음과 같습니다 .-? : makefile이라는 재귀에서 성능을 향상시킬 수 있습니다. 예를 들어 $? = $ (쉘 some_command_that_runs_long_time). 재귀 호출에서는 한 번만 평가됩니다. 빌드 성능이 향상되었습니다. : = 명령이 불필요하게 여러 번 실행되므로 속도가 느려질 것입니다.
KeshV

61

"make"를 사용하여 실험 해 보시기 바랍니다. 다음은 간단한 데모 차이 도시이다 =:=.

/* 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 인쇄물:

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

더 자세한 설명을 확인하십시오.


5
@혼란스러운 결과 반복을 피하기 위해 각 레시피 앞에 in 을 사용하는 것이 좋습니다 .
Alexandro de Oliveira

2
make는 /* ... */블록 주석을 지원하지 않습니다
yoonghm

31

를 사용할 때 실제로 다른 변수에 대한 참조 VARIABLE = value인 경우 valueVARIABLE은 사용될 때만 결정 됩니다. 이것은 예제와 함께 가장 잘 설명됩니다.

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

# VARIABLE and VAL will both evaluate to "bar"

당신이 사용할 때 VARIABLE := value, 당신 value 은 지금 의 가치를 얻습니다 . 예를 들면 다음과 같습니다.

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

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

사용 VARIABLE ?= valVARIABLE ifVARIABLE이 아직 설정되지 않았 음을 의미합니다 . 아직 설정되지 않은 경우 값 설정 VARIABLE은 사용할 때까지 연기 됩니다 (예 1에서와 같이).

VARIABLE += value에 추가 value합니다 VARIABLE. 실제 값 value이 초기에 사용하거나, 집합 된 시점의 판단 =이나 :=.


실제로 첫 번째 예에서 VARIABLE은 $ (VAL)이고 VAL은 bar입니다. VARIABLE을 사용할 때 확장되었습니다.
strager

1
그렇습니다. 의견은 그들이 사용될 때 일어날 일을 설명하고 있습니다.
mipadi

아; 나는 당신이 그것을 수정했다고 생각하거나, "평가하다"를 "be"로 잘못 읽었습니다.
strager

7

위의 답변에서 "값은 선언 / 사용시 확장됩니다"의 의미 를 이해 하는 것이 중요합니다 . 같은 가치를 부여하는 *.c것은 확장이 수반되지 않습니다. 명령에서이 문자열을 사용하는 경우에만 일부 globbing을 트리거 할 수 있습니다. 마찬가지로, 값은 확장을 수반 $(wildcard *.c)하거나 포함 $(shell ls *.c)하지 않으며 :=변수 정의에 사용한 경우에도 정의시 완전히 평가 됩니다.

C 파일이있는 디렉토리에서 다음 Makefile을 시도하십시오.

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

실행 make하면 추가 (빈) C 파일을 작성하는 규칙이 트리거 foo.c되지만 6 개의 변수 중 어느 것도 foo.c값에 없습니다.


이것은 훌륭한 부름이며 선언시 확장에 대한 많은 예제를 가지고 있습니다. 예를 들어 사용시 확장에 대한 예제와 일부 단어로 답변을 확장하는 것이 유용합니다
Robert Monfera
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.