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 = literal와 VARIABLE := 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인 경우 value값 VARIABLE은 사용될 때만 결정 됩니다. 이것은 예제와 함께 가장 잘 설명됩니다.

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 ?= val은 VARIABLE if 값 VARIABLE이 아직 설정되지 않았 음을 의미합니다 . 아직 설정되지 않은 경우 값 설정 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.