[MAKE] How to Use Variables
CS/Shell/Perl/Python 2011. 6. 8. 06:526.1 Basics of Variable References
변수 이름에는 대문자를 사용하는 것이 관행이다.
하지만, makefile 안에서 internal purpose 을 수행하는 것은 소문자를 사용하고, 암묵적인 규칙을 제어하는 파라매터나 컴맨드 옵션에서 사용자가 오버라이드 해야만 하는 파라메터에 대해서는 대문자로 예약할 것을 것을 권장 한다.
$(foo) 나 ${foo} 와 같이 변수 이름을 () 나 {}로 감사고 $를 붙여서 참조할 수 있다.
6.2 The Two Flavors of Variables
GNU make 에서는 변수가 값을 갖도로 하는 네 가지 방법이 있다.
- recursive expanded variable
이 종류의 변수는 '='를 통해서 정의하거나(Section 6.5 [Setting Variables] 참고), define 지시자를 통해서 정의될 수 있다.
만약 다른 변수에 대한 참조를 포함하고 있다면, 이 참조는 이 변수가 치환될 때마다 확장된다.
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
에서 $(foo)는 $(bar)로 확장되고, 이것은 다시 $(ugh)로 확장되어, 최종적으로 Huh? 로 확장될 것이다.
이 종류의 변수는 모든 다른 make에서도 지원한다. 하지만
CFLAGS = $(include_dirs) -O
include_dirs = -Ifoo -Ibar
CFLAGS = $(CFLAGS) -O
- expanded variable
변수가 정의될 때 어떤 다른 변수나 함수에 대한 참조를 확장하여 한번만 스캔 되고 확장된다. 즉, 이 변수가 정의 되었을 때의 값을 가진다.
x := foo
y := $(x) bar
x := later
는,
y := foo bar
x := later
와 같다.
- ?=를 이용해서 변수가 정의되어 있지 않을때만 정의할 수 있다.
FOO ?= bar 는
ifeq ($(origin FOO), undefined)
FOO = bar
endif
와 동일하다.
만약 bar 가 정의되어 있지 않았을 때 FOO = bar 와 같이 한다면, FOO는 empty value로 정의된 상태가 된다.
- +=를 이용하여 이미 정의된 변수의 값에 추가로 문자를 더할 수 있다.
objects = main.o foo.o bar.o utils.o
objects += another.o
+=를 사용하는 것은 :=를 다음과 같이 사용하는 것과 유사하다.
objects = main.o foo.o bar.o util.o
objects := $(objects) another.o
만약 +=로 덧붙일 변수가 이전에 정의되어 있지 않았다면, +=는 =(recursively-expanded variable)과 동일하게 동작한다.
6.3 Advanced Features for Reference to Variables
- substitution reference
지정한 대치값으로 변수의 값을 치환한다. $(var:a=b) 혹은 ${var:a=b}와 같은 형식으로 사용되며, var 변수에 있는 a로 끝나는(다음에 whitespace가 나오는 a) 모든 a를 b로 치환한다.
foo := a.o b.o c.o
bar := $(foo:.o=.c)
는 bar 를 a.c b.c c.c 로 치환한다.
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
는 $(patsubst .o,.c,$(var))와 동일하다.
- computed variable name (nested variable reference)
변수들은 변수의 안에 있는 이름으로 참조될 수 있다. 이를 computed variable name 혹은 nested variable reference라고 한다. 예를 들어
x = y
y = z
a :=$($(x))
에서 $($(x)는 $(y)가 되어, 결국 z가 된다.
혹은 재귀적으로
x = $(y)
y = z
z = Hello
a := $($(x))
에서 $($(x)) 는 $($(y))가 되고, 이것은 $(z) 가 되어, 결국 Hello가 된다.
Nested variable 참조는 변경된 참조나 함수 실행(Chapter 8 [Functions for Transforming Text] 참고) 등을 포함할 수 있다. 예를 들어 subst 함수를 사용하여
x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z))))
$($($(z)))는 $($(y))가 되고, y는 variable2의 값을 가지게 되기 때문에, $(variable2)가 되어, 결국 Hello를 정의하게 된다.
computed variable name은 하나의 변수 참조로 이루어질 필요는 없다. 예를 들어
a_dirs := dira dirb
1_dirs := dir1 dir2
a_files :=filea fileb
1_files :=file1 file2
ifeq "$(use_a)" "yes"
a1 := a
else
a1 := 1
endif
ifeq "$(use_dirs)" "yes"
df := dirs
else
dif := files
endif
dirs := $($(a1)_$(df))
$(a1) 이 a를 정의하고 $(df)가 dirs를 정의한다면, a_dirs가 되어 dirs 는 $(a_dirs)가 되어 결국,
dirs := dira dirb
를 정의하게 된다.
computed variable name은 치환 참조에서도 사용될 수 있다.
a_objects := a.o b.o c.o
1_objects := 1.o 2.o c.o
sources := $($(a1)_objects:.o=.c)
는 a1이 어떤것을 가리키느냐에 따라
sources := a.c b.c c.c
혹은
sources :=1.c 2.c 3.c
가 될 수 있다.
또한, computed variable name을 변수 대입의 왼편이나 define 지시자에서 사용할 수 있다.
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print =
lpr $($(dir)_sources)endef
이는 foo_sources와 foo_print를 정의한다.