Shell Function

shell 함수는 sh -c 형태로 프로세스를 생성하여 shell 명령을 실행합니다 ( 실행할 명령이 하나일 경우는 직접 실행 ). 명령 실행 결과 stdout 출력이 반환값이 되는데 이때 make 에 의해 newline 이 모두 space 로 변경되어 하나의 라인으로 됩니다. trailing newline 이 있을경우 제거되고 stderr 출력은 변경없이 그대로 출력됩니다.

.SHELLFLAGS 변수 설정값도 동일하게 shell 함수 실행시 적용됩니다. make 4.2.1 버전에 새로 추가된 .SHELLSTATUS 변수를 이용하면 종료 상태 값도 확인할 수 있습니다.


$(info $(shell find /bin/ -name 'p*'))

#######  실행 결과  ######
sh$ find /bin/ -name 'p*'
/bin/pwd
/bin/ping6
/bin/plymouth
/bin/ping4
/bin/pidof
/bin/ps
/bin/ping

sh$ make        # stdout 출력은 newline 이 모두 space 로 변경된다.
/bin/pwd /bin/ping6 /bin/plymouth /bin/ping4 /bin/pidof /bin/ps /bin/ping
$(info $(shell date -@; date))          # 오류를 위한 'date -@' 명령
$(info $(.SHELLSTATUS))

$(info ----------------------------)

.SHELLFLAGS += -e                       # errexit 쉘 옵션 추가
$(info $(shell date -@; date))
$(info $(.SHELLSTATUS))

#######  실행 결과  ######

date: invalid option -- '@'             # stderr 출력은 변경없이 그대로 출력된다.
Try 'date --help' for more information.
Sat 08 Jun 2019 07:54:04 PM KST         # 두 번째 date 명령은 정상 종료가 되므로
0                                       # 종료 상태 값은 0 이된다.
----------------------------
date: invalid option -- '@'
Try 'date --help' for more information. # errexit 쉘 옵션 설정에 의해 첫 번째 명령에서 
                                        # 쉘이 종료되어 두 번째 date 명령은 실행되지 않는다.
1                                       # 종료 상태 값은 1 이된다.

multi-line variable 을 사용하더라도 shell 함수에서는 newlne 이 적용되지 않으므로 ; 문자를 사용해야 합니다.

define foo                               define foo
echo 11111                               echo 11111;   # ';' 문자를 사용해야 한다.
echo 22222                               echo 22222;
echo 33333                               echo 33333
endef                                    endef

$(shell { $(foo) ;} >&2)                 $(shell { $(foo) ;} >&2)

######  실행 결과  ######                  ######  실행 결과  ######
11111echo 22222echo 33333                11111
                                         22222
                                         33333

만약에 stdout 출력도 newline 을 포함해 그대로 출력하고 싶으면 다음과 같은 방법을 사용할 수 있습니다.

bel != printf '\007'
define nl


endef
$(info aaa$(nl)bbb)
$(info $(subst $(bel),$(nl),$(shell { find /bin/ -name 'p*' ;} | tr '\n' '\a' )))

########  실행 결과  ########
sh$ make
aaa
bbb
/bin/pwd
/bin/ping6
/bin/plymouth
/bin/ping4
/bin/pidof
/bin/ps
/bin/ping