Go to the first, previous, next, last section, table of contents.


Makefile의 조건 부분(Conditional Parts of Makefiles)

조건(conditional) 은 makefile의 어떤 부분이 변수의 값에 따라서 사용되거나 무시되도록 한다. 조건은 한 변수를 다른 것과, 또는 한 변수의 값을 상수 문자열과 비교할 수 있다. 조건은 make가 실제로 makefile에서 "보는" 것을 제어한다. 그러므로 실행시의 쉘 명령들을 제어하는 데에는 사용될 수 없다.

조건의 예(Example of a Conditional)

다음 조건의 예제는 make에게 CC 변수가 `gcc'이라면 일단의 라이브러리 모음을 사용하라고 말하는 것이다. 그렇지 않다면 다른 라이브러리 모음을 사용하도록 말하는 것이다. 두 명령 라인들 중의 어떤 것이 어떤 규칙에 대해서 사용될 것인가를 제어함으로써 작동한다. 그 결과로 make에 대한 매개변수로써 `CC=gcc'를 쓰면, 어떤 컴파일러가 사용될 것인가 뿐만 아니라 어떤 라이브러리들이 링크될 것인가를 변경한다.

libs_for_gcc = -lgnu
normal_libs =

foo: $(objects)
ifeq ($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
else
        $(CC) -o foo $(objects) $(normal_libs)
endif

이 조건은 세가지 지시어들을 사용한다: 하나는 ifeq, 하나는 else, 그리고 나머지 하나는 endif.

ifeq 지시어는 조건을 시작하고 조건을 지정한다. 콤머로 분리되고 괄호로 둘러싸인 두개의 매개변수들을 가진다. 변수 대입이 두 매개변수들에 대해서 수행되고 난 뒤에 그들이 비교된다. ifeq 뒤에 오는 makefile의 라인들은 두 매개변수들이 일치할 경우 사용된다; 그렇지 않으면 그들은 무시된다.

else 지시어는 다음 라인들이, 이전 조건이 실패하였다면, 수행되도록 한다. 위의 예제에서 이것은 두번째 대안 링크 명령이, 첫번째 대안이 사용되지 않을때마다, 사용된다는 것을 의미한다. else를 조건에 가지는 것은 선택이다.

endif 지시어는 조건을 종료한다. 모든 조건은 반드시 endif로 종료해야 한다. 이 뒤에 조건이 아닌 makefile의 텍스트가 온다.

예제가 예시하는 것처럼 조건은 텍스트 레벨에서 작동한다: 조건의 라인들은 조건에 따라서 makefile의 일부로 취급되거나 아니면 무시된다. 이것은 규칙과 같은 makefile의 더 큰 문법 유닛들이 왜 조건의 시작이나 끝과 겹쳐져 있을 수 있는가에 대한 이유이다.

변수 CC가 변수 `gcc'를 가질 때 위의 예제는 다음과 같은 효과를 가진다:

foo: $(objects)
        $(CC) -o foo $(objects) $(libs_for_gcc)

변수 CC가 임의의 다른 값을 가진다면 그 결과는 다음과 같을 것이다:

foo: $(objects)
        $(CC) -o foo $(objects) $(normal_libs)

어떤 변수 할당을 조건화해서 변수를 무조건 사용함으로써, 동일한 결과가 다른 식으로 얻어질 수 있다:

libs_for_gcc = -lgnu
normal_libs =

ifeq ($(CC),gcc)
  libs=$(libs_for_gcc)
else
  libs=$(normal_libs)
endif

foo: $(objects)
        $(CC) -o foo $(objects) $(libs)

조건의 문법(Syntax of Conditionals)

else를 가지지 않는 단순한 조건의 문법은 다음과 같다:

conditional-directive
text-if-true
endif

text-if-true는 임의 라인의 텍스트일 수 있다. 이것은 조건이 참일 때 makefile의 일부로 여겨진다. 조건이 거짓이면 어떤 텍스트도 사용되지 않는다.

복잡한 조건의 문접은 다음과 같다:

conditional-directive
text-if-true
else
text-if-false
endif

조건이 참이면 text-if-true가 사용된다; 그렇지 않으면 text-if-false 이 사용된다. text-if-false는 임의 라인의 텍스트일 수 있다.

conditional-directive 의 문법은 조건이 단순하든지 아니면 복잡하든지 동일하다. 서로 다른 조건들을 테스트하는 서로 다른 지시어들이 네개 있다. 이들은 다음과 같다:

ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
arg1arg2에 있는 모든 변수 참조들을 확장하고서 그들을 비교한다. 그들이 서로 같다면 text-if-true가 사용될 것이고; 그렇지 않다면 text-if-false가, 있다면, 사용될 것이다. 어떤 변수가 빈것이 아닌 값을 가진것인가 아닌가를 테스트하고자 할 경우가 많다. 값이 변수와 함수의 복잡한 확장으로부터 온 것일 때, 빈것으로 생각한 확장이 실제로 공백문자들을 담고 있어서 빈것으로 보이지 않을 수도 있다. 그러나 strip 함수 see section 문자 대입과 분석을 위한 함수들(Functions for String Substitution and Analysis)) 를 사용해서 공백문자를 빈것이 아닌 값으로 해석하는 것을 피할 수 있다. 예를 들면:
ifeq ($(strip $(foo)),)
text-if-empty
endif
이것은 $(foo) 의 확장이 공백문자를 담고 있다고 하더라도 text-if-empty 를 평가할 것이다.
ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"
이것은 arg1arg2에 있는 모든 변수 참조들을 확장한 뒤 그것들을 비교한다. 그들이 다르다면 text-if-true 가 사용될 것이고; 그렇지 않다면 text-if-false가, 존재한다면, 사용될 것이다.
ifdef variable-name
변수 variable-name 가 빈것이 아닌 값을 가진다면, text-if-true 가 사용될 것이다; 그렇지 않다면 text-if-false 가, 존재한다면, 사용될 것이다. 한번도 정의된 바가 없는 변수들은 빈 값을 가진다. ifdef 는 어떤 변수가 값을 가지는지 안가지는지에 대해서만 테스트한다는 것에 주의하자. 이것은, 값이 빈것인가 아닌가를 보기 위해서 변수를 확장하지 않는다. 결과적으로 ifdef를 사용한 테스트들은 foo =와 같은 것들을 제외한 모든 정의들에 대해서 참을 리턴한다. 빈 값에 대한 테스트를 하려면 ifeq ($(foo),) 를 사용한다. 예를 들어서,
bar =
foo = $(bar)
ifdef foo
frobozz = yes
else
frobozz = no
endif
이것은 `frobozz'`yes'로 설정하는 반면에 다음은:
foo =
ifdef foo
frobozz = yes
else
frobozz = no
endif
`frobozz'`no'로 설정한다.
ifndef variable-name
variable-name 변수가 빈 값을 가진다면 text-if-true 가 사용된다; 그렇지 않으면 text-if-false, 존재한다면, 사용된다.

조건 지시어 라인에서 맨앞에 있는 여분의 공백들은 허용되고 이들은 무시된다. 그러나 탭은 허용되지 않는다. (탭으로 시작한다면 규칙의 명령으로 생각될 것이다.) 이런 것 외에 여분의 공백들이나 탭들이 지시어 이름이나 매개변수 안을 제외하고는, 어디에서나 아무런 효과없이 삽입될 수 있다. `#' 로 시작하는 주석이 라인의 마지막에 올 수 있다.

조건의 일부인 다른 두 지시어들은 elseendif이다. 이런 지시어들 각각은 단일 워드로, 매개변수 없이 사용된다. 여분의 공백들이 그 라인의 맨처음에 올 수도 있으며 이들은 무시된다. 그리고 라인의 끝에 공백들이나 탭들이 올 수 있다. `#'로 시작하는 주석은 라인의 끝에 나타날 수 있다.

조건은 makefile의 어떤 라인들을 make가 사용할 것인가에 영향을 미친다. 조건이 참이면, maketext-if-true 라인들을 makefile의 일부로 읽는다; 조건이 거짓이면 make는 이런 라인들을 완전히 무시한다. 규칙과 같은 makefile의 문법 유닛들이 조건의 끝이나 처음에 걸쳐 안전하게 쪼개질 수 있다.

make는 그것이 makefile을 읽을 때 조건들을 평가한다. 결과적으로 조건의 테스트 안에서 자동 변수들을 사용할 수 없다. 왜냐면 그들은 명령들이 실행되기 전에는 정의되지 않기 때문이다 (see section 자동 변수들(Automatic Variables)).

참을수 없는 혼동을 막기 위해서 하나의 makefile안에서 조건을 시작하고 다른 makefile 안에서 끝내지는 것은 허용되지 않는다. 그러나, include 지시어를 조건 안에 사용할 수 있다. 단 그 include된 파일 안에서 그 조건을 종료하려고 시도하지 않는다면 말이다.

플래그 검사 조건(Conditionals that Test Flags)

`-t'와 같은 make 명령 플래그들을, 변수 MAKEFLAGSfindstring 함수 (see section 문자 대입과 분석을 위한 함수들(Functions for String Substitution and Analysis)) 를 사용함으로써, 검사하는 조건을 작성할 수 있다. 이것은 touch가 파일이 업데이트된 것으로 만들기에 충분하지 않을 때 유용하다.

findstring 함수는 한 문자열이 다른 것의 부분문자열로 나타난 것인가 아닌가를 결정한다. `=t' 플래그를 테스트하고자 한다면 `t'를 첫번째 문자열로, MAKEFLAGS를 다른 문자열로 사용한다.

예를 들어서 다음은 아카이브 파일이 갱신된 것으로 표시하는 것을 끝내도록 하기 위해서, `ranlib -t'를 사용해서 정리하는 방법이다:

archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
        +touch archive.a
        +ranlib -t archive.a
else
        ranlib archive.a
endif

`+' 프리픽스는 이런 명령 라인들이 "재귀적" 이어서 그들이 `-t' 플래그에도 불구하고 실행될 것이라는 것을 표시한다. See section make의 재귀적 사용(Recursive Use of make).


Go to the first, previous, next, last section, table of contents.