Conditional Directives
조건 지시자는 C/C++ 언어의 전처리기 에서처럼 특정 코드를 조건에 따라 포함하거나 제외하고자 할 때
사용합니다.
makefile 의 모든 부분에서 적용할 수 있으나 recipe 가 실행되기 전에 처리가 완료되므로
recipe 실행 중에 처리를 위해서는 사용할 수 없습니다.
기본적으로 ifxxxx ~ else ~ endif
형식을 가지는데 else
지시자는 옵션으로
사용되지 않을 경우 제외할 수 있습니다.
recipe 실행 중에 automatic 변수와 함께 조건문을 사용하려면 Conditional built-in 함수를 사용합니다.
ifeq , ifneq . . . else . . . endif
값 비교에는 다음과 같은 3 가지 형식을 사용할 수 있습니다. quotes 을 사용하는 형식은 quotes 이 중첩될 경우 오류가 발생할 수 있으므로 주의해야 합니다.
ifeq (arg1,arg2) ifneq (arg1,arg2)
ifeq "a" "b" ifneq "a" "b"
ifeq 'a' 'b' ifneq 'a' 'b'
-------------------------------------------------
# shell 함수에서 사용하는 quotes 과 중첩되어 오류가 발생한다.
ifeq "$(shell echo "foo bar")" "foo bar"
$(info 11111 )
endif
실행결과: Makefile:1: *** unterminated call to function 'shell': missing ')'. Stop.
# 이때는 괄호형을 사용하거나 변수에 대입해서 사용하면 됩니다.
ifeq ($(shell echo "foo bar"),foo bar)
$(info 11111 )
endif
실행결과: 11111
( )
괄호형을 사용할 때는 가운데 공백은 값에 포함되지 않지만
양끝에 공백은 값에 포함되므로 주의해야 합니다.
따라서 다음 세 번째 예제의 경우 실제 값은 " foo"
와 "foo "
가 되어 거짓이 됩니다.
$ make -f- <<\@ $ make -f- <<\@ $ make -f- <<\@
ifeq (foo,foo) ifeq (foo , foo) ifeq ( foo,foo )
$(info equal) $(info equal) $(info equal)
else else else
$(info not equal) $(info not equal) $(info not equal)
endif endif endif
@ @ @
equal equal not equal
ifdef , ifndef . . . else . . . endif
ifdef
, ifndef
지시자는 flavor, origin 함수에서 사용되는
undefined 상태를 체크하는 것이 아니고 값이 empty 인지 아닌지를 체크합니다.
따라서 변수가 존재하나 값이 empty 일 경우와 undefined 상태일 경우
모두 ifndef
에서는 참이 됩니다.
ifdef variable ifndef variable
--------------------------------------------------------
AA :=
ifndef AA # 변수가 존재하지만 empty 이므로 참이된다.
$(info AA is not defined or empty )
endif
####### 실행 결과 ######
AA is not defined or empty
and , or 연산
조건 지시자에는 기본적으로 and, or 연산자가 없습니다. 따라서 다음과 같이 사용해야 합니다.
ifeq (arg1,arg2) ---- (1)
ifeq (arg1,arg2) ---- (2)
# (1) and (2) 가 참이면 실행
endif
endif
----------------------------------------
ifeq (arg1,arg2) ---- (1)
# (1) 이 참이면 실행
else ifeq (arg1,arg2) ---- (2)
# (1) 이 거짓이고 (2) 는 참이면 실행
else
# (1), (2) 모두 거짓이면 실행
endif
strip 함수의 사용
if
함수의 condition 부분이 아닌 반환값에 사용되는 then, else 파트 부분에서는
공백도 하나의 값으로 인식됩니다. 따라서 \
문자를 이용해 개행을 해서 작성할때는
반드시 strip
함수를 사용해야 합니다.
aa := foo aa := foo
bb := bb :=
# strip 함수 사용
ifneq "$(if $(aa), $(bb))" "" ifneq "$(strip $(if $(aa), $(bb)))" ""
$(info 1111111111) $(info 1111111111)
endif endif
####### 실행 결과 ####### ####### 실행 결과 #######
$ make $ make
1111111111 $
------------------------------------------------------------------------------
# if 함수의 then, else 파트 부분에 공백이 있어서 ifneq 조건 지시자는 무조건 참이 된다.
ifneq "$(if $(MAKECMDGOALS), \
$(filter all clean all.% clean.%,$(MAKECMDGOALS)), \
$(filter all clean all.% clean.%,$(.DEFAULT_GOAL)))" ""
# 값으로 인식되는 공백을 제거하기 위해 strip 함수를 사용해야 한다.
ifneq "$(strip $(if $(MAKECMDGOALS), \
$(filter all clean all.% clean.%,$(MAKECMDGOALS)), \
$(filter all clean all.% clean.%,$(.DEFAULT_GOAL))))" ""
사용 예제 )
1 . recipe 에서 사용할 경우
# recipe 에서 실행되므로 shell 명령을 작성할 때는 앞에 tab 문자를 붙입니다.
prog : $(OBJS)
ifeq "$(MYVAR)" "foo"
$(CC) $+ $(libs_for_foo) -o $@ # tab
else
$(CC) $+ $(normal_libs) -o $@
endif
2 . global 영역에서 사용할 경우
ifeq "$(MYVAR)" "foo"
prog : foo.o bar.o zoo.o
$(CC) $+ -o $@
else
prog : xxx.o yyy.o zzz.o
$(CC) $+ -o $@
endif