[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3. 메이크파일 작성하기

한 시스템을 다시 컴파일하는 방법을 make에게 알려주는 정보는 메이크파일(makefile)이라고 하는 데이타베이스를 읽음으로써 얻어진다.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 메이크파일에 무엇이 들어 있는가

메이크파일은 다섯가지 종류의 것들이 들어 있다: 명시적 룰, 암묵적인 룰, 변수 정의, 지시어, 그리고 주석문이다. 룰, 변수, 그리고 지시어는 뒤에서 더 자세히 설명한다.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 메이크파일을 어떤 이름으로 할 것인가

기본 사항으로, make가 메이크파일을 찾을 때, 다음 이름들을 순서대로 시도한다: ‘GNUmakefile’, ‘makefile’ 그리고 마지막으로 ‘Makefile’이다.

보통 메이크파일을 ‘makefile’이나 ‘Makefile’이라고 이름지을 것이다. (우리는 ‘Makefile’을 추천한다. 이렇게 하면 이 파일은 디렉토리 리스트의 처음부분에 ‘README’와 같은 중요한 파일들 다음에 나타날 것이기 때문이다.) 첫번째로 검사되는 이름은 ‘GNUmakefile’은 대부분의 메이크파일의 경우 추천되지 않는다. GNU make 전용 메이크파일일 경우에만 이 이름을 사용해야 하고, 이 이름은 다른 make 버전에서는 이해할 수 없을 것이다. 다른 make 프로그램은 ‘makefile’과 ‘Makefile’을 검사하고, ‘GNUmakefile’은 검사하지 않는다.

make가 이런 이름의 파일을 하나도 찾지 못한 경우, 메이크파일을 아예 사용하지 않을 것이다. 이 경우에는 make 명령의 인자로 골을 지정해야 하고, make는 이미 내부에 들어 있는 암묵적인 룰만을 사용해 그 골을 다시 만드려고 시도할 것이다. See section 암묵적인 룰 사용하기.

메이크파일 이름으로 표준이 아닌 이름을 쓰고 싶으면, ‘-f’ 혹은 ‘--file’ 옵션에 그 메이크파일의 이름을 지정할 수 있다. ‘-f name’ 혹은 ‘--file=name’ 인자를 주면 make는 메이크파일로 name 파일을 읽는다. 한 개 이상의 ‘-f’ 혹은 ‘--file’ 옵션을 사용하면 여러개의 메이크파일을 지정할 수 있다. 모든 메이크파일은 지정한 순서대로 연결도니다. 기본 메이크파일의 이름인 ‘GNUmakefile’, ‘makefile’ 그리고 ‘Makefile’은 ‘-f’ 혹은 ‘--file’을 지정했을 경우 자동으로 검사되지 않는다.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 다른 메이크파일 포함하기

include 지시어를 사용하면 make는 잠시 현재 메이크파일 읽기를 중단하고 또다른 메이크파일을 읽은 다음 현재 메이크파일을 계속해서 읽는다. 메이크파일에서 이 지시어는 다음과 같이 쓴다:

 
include 파일이름

파일이름으로 셀 방식의 파일이름 패턴을 사용할 수 있다. 줄이 시작할 때 공백을 넣어도 되고, 이 공백은 무시된다. 하지만 탭은 쓸 수 없다. (줄이 탭으로 시작하면 그 줄은 커맨드 라인으로 이해할 것이다.) include와 파일 이름 사이, 그리고 파일 이름들 사이에 공백을 넣어야 한다; 여기에 공백을 여러개 넣거나 줄의 끝에 공백을 넣어도 무시된다. 줄 끝에 ‘#’로 시작하는 주석문을 쓸 수도 있다. 파일 이름에 변수나 함수 참조가 들어 있으면, 그 변수나 함수는 그 값으로 대체된다.

예를 들어, ‘a.mk’, ‘b.mk’, 그리고 ‘c.mk’ 세개의 ‘.mk’ 파일이 있고, $(bar)의 값이 bish bash인 경우, 다음

 
include foo *.mk $(bar)

는 다음과 같다.

 
include foo a.mk b.mk c.mk bish bash

makeinclude 지시어를 처리할 때, include가 들어 있는 메이크파일 읽기를 잠시 중단하고 include에 열거된 파일들을 순서대로 읽는다. 읽기가 모두 끝나면, makeinclude 지시어가 들어 있는 메이크 파일 읽기를 다시 계속한다.

include 지시어를 사용하는 한가지 상황은 여러 개의 디렉토리에 있는 각 메이크파일로 처리되는 여러개의 프로그램이 같은 종류의 변수 정의를 사용해야 할 경우이다. (see section Setting Variables) or pattern rules (see section Defining and Redefining Pattern Rules).

도다른 상황은 소스 파일에서 의존성을 자동으로 만들어 내는 경우이다; 의존성은 메인 메이크파일이 포함하는 파일 안에 들어 있게 된다. 이렇게 이용하는 일은 메인 메이크파일의 끝에 의존성을 추가하는 것보다 (다른 버전의 make에서 전통적으로 해 왔던 방법이다) 더 깨끗한 방법이다. See section Generating Dependencies Automatically.

여기서 지정한 파일 이름이 슬래쉬로 시작하지 않으면서, 현재 디렉토리에 없으면, 몇개의 다른 디렉토리들에서 이 파일을 찾아본다. 맨 먼버 ‘-I’ 혹은 ‘--include-dir’ 옵션으로 지정한 디렉토리에서 찾는다 (see section Summary of Options). 그 다음에 다음 디렉토리(이런 디렉토리가 있다면)에서 순서대로 찾는다: ‘prefix/include’ (보통 ‘/usr/local/include(1)) ‘/usr/gnu/include’, ‘/usr/local/include’, ‘/usr/include’.

포함할 메이크파일이 이 디렉토리들의 어디에도 없으면, 경고 메세지가 나오지만, 즉시로 치명적인 애러가 되지는 않는다; include가 들어 있는 메이크파일을 계속 처리한다. 일단 메이크파일 읽기를 마치면, make는 오래되었거나 존재하지 않는 메이크파일들을 다시 만드려고 시도할 것이다. See section 메이크파일 다시 만드는 법. 메이크파일을 다시 만드려고 시도하고 실패한 다음에서야, make는 메이크파일이 없다는 치명적 애러를 낸다.

존재하지 않고, 다시 만들 수 없는 메이크 파일을 애러 메세지 없이 make가 무시하도록 하려면, -include 지시어를 include 대신에 다음과 같이 사용한다:

 
-include 파일이름

이건 모든 면에서 include과 같지만 파일이름이 없어도 애러를 내지 않는다 (경고 조차도 내지 않는다). 다른 버전의 make와 호환되도록 하기 위해, -include의 또다른 이름으로 sinclude가 있다.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.4 The Variable MAKEFILES


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.5 변수 MAKEFILES

MAKEFILES 환경변수가 정의되면, make는 이 값을 다른 메이크파일을 읽기 전에 읽어야 할 추가 메이크파일의 파일이름 리스트(공백으로 구분된)라고 생각한다. 이 환경 변수는 include 지시어와 아주 비슷하게 동작한다: 여러개의 디렉토리에서 이 파일이 있는지 찾는다 (see section Including Other Makefiles). 다른 점이 있다면, 기본 골은 이 메이크파일에 있는 타겟을 사용하지 않고, MAKEFILES에 열거도니 파일이 없더라도 애러가 아니다.

MAKEFILESmake를 재귀적으로 사용할 경우 각 make 사이의 통신 목적으로 주로 사용된다. make를 맨 처음 실행하기 전에 이 환경변수를 지정하는 일은, 외부의 메이크파일때문에 현재 읽는 메이크파일이 엉망이 될 염려가 있으므로 보통 좋지 않은 일이다. 하지만 어떤 메이크파일이 없이 make를 실행하는 경우, MAKEFILES의 메이크 파일은 내부의 암묵적인 룰들을 더 잘 동작시키도록 하는 데 매우 유용하게 쓰일 수 있다. 예를 들어 찾기 경로를 정의하는 데 유용하게 쓰인다 (see section 의존성이 들어 있는 디렉토리 찾기).

어떤 사람들은 로긴할 때 자동으로 MAKEFILES 값을 결정하도록 맞춰놓고, MAKEFILES 값이 존재한다고 가정하고 메이크파일을 작성한다. 이건 매우 좋지 않은 방법이다. 그렇게 만들어진 메이크 파일은 다른 사람이 사용할 때 제대로 동작하지 않을 것이기 때문이다. 메이크 파일에 직접 include 지시어를 쓰는 편이 훨씬 좋다. See section 다른 메이크파일 포함하기.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.6 메이크파일 다시 만드는 법

가끔 메이크파일이 다른 파일에서부터 다시 만들어지는 경우도 있다. 예를 들어 RCS 혹은 SCCS 파일에서부터 만들어 질 수 있다. 메이크파일이 다른 파일에서 만들어 질 수 있는 경우, 아마 make가 최신 버전의 메이크파일을 읽어들이길 바랄 것이다.

모든 메이크 파일을 읽은 다음에, make는 각각의 메이크파일에서 골 타겟을 찾아내고 업데이트를 시도한다. 메이크파일에 어떻게 업데이트하라고 알려주는 (바로 그 메이크파일에 있거나 다른 메이크 파일에 있거나) 룰이 하나도 없거나 암묵적인 룰이 거기에 적용되는 경우 (see section 암묵적인 룰 사용하기), 필요한 경우에만 업데이트될 것이다. 모든 메이크파일이 검사된 다음에, 메이크파일이 하나라도 변경되었으면, make는 지금까지 읽은 걸 모두 잊어버리고, 메이크파일 전체를 다시 읽는다. (각 메이크파일을 또다시 업데이트하려고 시도하기도 한다. 하지만 이 파일들은 이미 업데이트되어 있으므로 보통의 경우 또다시 메이크파일을 바꾸지는 않을 것이다.)

메이크파일에 의존성 없이 파일을 다시 만드는 더블 콜론이 있으면, 그 파일은 언제나 다시 만들 것이다 (see section Double-Colon Rules). 메이크파일의 경우, 더블 콜론 룰이 의존성 없이 명령어만 있는 메이크파일의 경우에는 make가 실행될 때마다 다시 만들어질 것이고, make는 또다시 메이크파일들을 읽기 시작할 것이다. 무한 루프를 돌게 된다: make는 계속해서 메이크파일들을 다시 만들고, 그 외의 아무 것도 하지 않는다. 즉, 무한 루프를 막으려면, make가 더블 콜론 타겟에서 의존성 없이 메이크파일을 다시 만들지 않도록 해야 한다.

-f’ 혹은 ‘--file’ 옵션으로 읽을 메이크파일을 특별히 지정하지 않으면, make는 기본 메이크파일 이름들을 시도한다; see section What Name to Give Your Makefile. 명시적으로 메이크파일을 ‘-f’ 혹은 ‘--file’ 옵션으로 요청했을 경우와는 다르게, make는 이 메이크파일이 진짜로 존재하는 지, 안 하는지 신경을 쓰지 않는다. 하지만 기본 메이크파일이 존재하지 않지만 make 룰을 실행해서 기본 메이크파일을 만들 수 있는 경우라면, 그 룰을 실행해서 메이크파일이 사용될 수 있도록 하고 싶을 것이다.

즉, 기본 메이크파일이 아무것도 없으면, make는 각 기본 메이크파일들을 찾는 순서와 같은 순서로 (see section What Name to Give Your Makefile) 하나라도 만드는 데 성공할 때까지, 혹은 모든 이름들을 다 시도할 때까지, 만드려고 시도한다. make가 메이크파일을 찾지도 못하고, 만들지도 못한 경우에도 애러가 아니라는 점에 유의하라; 메이크파일은 항상 필요한 것이 아니다.

-t’ 혹은 ‘--touch’ 옵션을 사용하는 경우 (see section Instead of Executing the Commands), 어느 타겟을 touch하는지 결정하는 데 뒤떨어진 메이크파일을 사용하고 싶지는 않을 것이다. 즉 ‘-t’ 옵션은 메이크파일을 업데이트할 때는 아무런 효과가 없다; 메이크 파일은 ‘-t’가 지정된 경우에도 진짜로 업데이트된다. 마찬가지로, ‘-q’(혹은 ‘--question’)과 ‘-n’(혹은 ‘--just-print’) 옵션도 메이크파일 업데이트를 막을 수는 없다. 뒤떨어진 메이크파일은 그 외의 타겟에 대해 잘못된 결과를 낼 수도 있기 때문이다. 즉, ‘make -f mfile -n foo’ 명령은 ‘mfile’을 업데이트하고, 그 파일을 읽고, ‘foo’와 그 의존성을 업데이트하는 명령들을 실행하지는 않고 표시만 할 것이다. ‘foo’에 대해 표시되는 명령어들은 업데이트된 ‘mfile’에 쓰여 있는 명령어이다.

하지만, 가끔 진짜로 메이크파일 조차 업데이트하지 않도록 하고 싶을 때가 있다. 메이크 파일을 명령행에서 골로 지정함과 동시에 메이크파일로 지정하면 그렇게 할 수 있다. 메이크파일 이름이 직접 골로 지정된 경우, ‘-t’ 옵션 등이 효과를 발휘한다.

그러므로, ‘make -f mfile -n mfile foo’는 ‘mfile’ 메이크파일을 읽고, 명령어를 실행하지 않은 채로 ‘mfile’을 업데이트할 때 필요한 명령어들을 표시한다. 그리고 ‘foo’를 업데이트할 때 필요한 명령어들을 실행하지 않은 채로 표시한다. ‘foo’의 명령어들은 ‘mfile’의 현재 내용에 쓰여 있는 명령어이다.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.7 다른 메이크파일의 일부를 무시하기

어떤 경우에는, 또 다른 메이크파일과 거의 비슷한 메이크파일이 있으면 유용하다. 어떤 메이크 파일을 ‘include’ 지시어를 사용해서 또다른 메이크 파일에서 포함하고, 더 많은 타겟과 변수 정의를 추가할 수도 있다. 하지만, 두개의 메이크파일이 같은 타겟에 대해서 다른 명령이 주어졌다면, make는 그런 식으로 하도록 내버려 두지 않는다. 그러나 한 가지 방법이 있다.

메이크 파일을 포함하는 (또 다른 메이크 파일을 포함하려는) 메이크파일에서 아무거나 맞는 패턴 룰을 써서 포함하는 메이크파일에 들어 있는 정보에서 만들 수 없는 타겟을 다시 만들도록, 그래서 make가 다른 메이크파일에서 타겟을 찾아보도록 할 수 있다. 패턴 룰에 대한 더 많은 정보는 See section Defining and Redefining Pattern Rules.

예를 들어, 어떻게 ‘foo’ 타겟을 (그리고 그 외 여러가지 타겟을) 만드는 법이 쓰여 있는 ‘Makefile’이라는 메이크파일이 있으면, 다음과 같이 들어 있는 ‘GNUmakefile’이라는 메이크파일을 작성할 수 있다.

 
foo:
        frobnicate > foo

%: force
        @$(MAKE) -f Makefile $@
force: ;

make foo’라고하면, make는 ‘GNUmakefile’을 찾고, 읽은 다음, ‘foo’를 만드려면 ‘frobnicate > foo’라는 명령을 실행해야 된다는 걸 알아 차린다. 만약 ‘make bar’라고 하면, make는 ‘GNUmakefile’에서는 ‘bar’를 만드는 법을 찾지 못하고, 패턴 룰에 있는 명령어를 사용할 것이다: ‘make -f Makefile bar’. ‘Makefile’에 ‘bar’를 업데이트하는 룰이 들어 있으면, make는 그 룰을 적용할 것이다. 그리고 어떻게 만드는지 ‘GNUmakefile’에 쓰여 있지 않은 다른 모든 타겟에 대해서도 마찬가지이다.

위와 같이 동작하는 이유는, 위의 패턴 룰에서 ‘%’라는 패턴을 사용하고 있으므로, 어떤 타겟에 대해서도 들어 맞기 때문이다. 이 룰은 ‘force’라는 의존성을 지정해서, 그 타겟 파일이 이미 존재하는 경우에도 명령이 실행되도록 보장한다. 우리는 ‘force’ 타겟에서 빈 명령을 집어 넣어서 make가 ‘force’를 빌드하는 암묵적인 룰을 찾지 않도록 한다—이렇게 하지 않으면 같은 아무거나 맞는 룰이 ‘force’ 자체에도 적용되어 의존성에 루프가 생긴다.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Autobuild on July 8, 2017 using texi2html 1.82.