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