Multi-Line Variables
make 은 기본적으로 라인 단위이므로 변수값을 설정할 때 newline 이 포함되지 않습니다.
하지만 define
~ endef
지시자를 이용하면 newline 을 포함할 수 있습니다.
변수명 뒤에는 대입 연산자가 올 수 있는데 생략할 경우 =
recusive 연산자가 사용됩니다.
# 변수, 함수 값으로 newline 을 사용할 수 있다. # 인수를 전달할때 newline 을 사용
define foo := define foo foo = $(info [$1] [$2] [$3])
111 $(info 111 define bar
222 222 $(call foo,1
333 333) 11,2
endef endef 22,3
33)
$(info $(foo)) $(foo) endef
#### 실행 결과 #### #### 실행 결과 ####
111 111 $(bar)
222 222 #### 실행 결과 ####
333 333 [1
11] [2
22] [3
33]
실행 중에 동적으로 rule 을 정의
multi-line 변수를 이용하면 실행 중에 동적으로 rule 을 정의할 수 있습니다.
아래 예제의 경우 call 함수 실행에 의해 $1
는 첫 번째 인수 값인 t1
이 되고
$2
는 두 번째 인수 값인 p1 p2 p3
가 됩니다.
$$
변수는 $
문자로 변경되므로 최종적으로 $@
와 $^
가 eval 함수로 전달되어
rule 이 정의됩니다.
rule 정의는 global 영역에서 완료되는 것으로 recipe 실행 중에는 동적으로 정의할 수 없습니다.
define onerule
$1 : $2
@echo target: $$@, prerequisites: $$^
endef
$(eval $(call onerule,t1,p1 p2 p3)) # eval 함수를 사용
.DEFAULT: ;
############# 실행 결과 #############
target: t1, prerequisites: p1 p2 p3
테스트할 때 오류가 발생하면 recipe 앞의 tab 문자를 확인해 보세요
multi-line 변수가 recipe 에서 사용될 경우
multi-line 변수라도 recipe 에서 사용될 경우는 각 라인별로 shell 프로세스가 생성되어 실행됩니다.
define foo
define foo $(if 111, # if 함수 사용
echo shell PID: $$$$ echo shell PID: $$$$
echo shell PID: $$$$ echo shell PID: $$$$
echo shell PID: $$$$ echo shell PID: $$$$)
endef endef
all : foo :
@$(foo) @$(foo)
###### 실행 결과 ###### ###### 실행 결과 ######
# 각 라인 별로 shell PID 가 다르다. # 각 라인 별로 shell PID 가 다르다.
shell PID: 18426 shell PID: 11206
shell PID: 18427 shell PID: 11207
shell PID: 18428 shell PID: 11208
명령이 모두 하나의 shell 프로세스에서 실행되게 하려면 다음과 같이 하나의 라인으로 작성해야 합니다.
define foo
echo shell PID: $$$$; \
echo shell PID: $$$$; \
echo shell PID: $$$$
endef
all :
@$(foo)
##### 실행 결과 #####
shell PID: 18550 # 동일한 shell PID
shell PID: 18550
shell PID: 18550
변수 작성시 #
comment 문자
multi-line 변수를 작성할 때는 #
문자가 주석으로 기능하지 않고 그대로 값으로 사용됩니다.
따라서 아래 첫 번째 예제에서 foo 변수값은 #
문자와 newline 이 됩니다.
( info 함수는 반환값이 empty 이므로 )
define foo define foo
#$(info 111) #
$(info 222) endef
$(info 333)
endef bar :
@echo 111 222
$(info xxx$(foo)yyy) @echo 333 $(foo) 444
### 실행 결과 ### ### 실행 결과 ###
111 <--- 주석 처리가 안된다 111 222
222 333 # shell 에서 '#' 문자가
333 # 주석으로 처리된다.
xxx#
yyy
newline 변수를 정의하는 방법
one-line 변수 정의에서는 기본적으로 newline 이 모두 space 로 변경되기 때문에 newline 문자를 값으로 갖는 변수를 정의할 수 없습니다. 따라서 이때는 multi-line 변수를 이용해야 합니다.
define nl :=
# newline 들이 space 로 변경된다.
$ make -f - <<\@ 2> /dev/null | od -a
AA != printf 'X\012\012\012X' endef
$(info Y$(AA)Y) $(info aaa$(nl)bbb)
@ ###### 실행 결과 ######
0000000 Y X sp sp sp X Y nl aaa
0000010 bbb