[OS]/Embedded

[펌] GNU Make: 재컴파일을 지휘하는 프로그램(A Program for Directing Recompilation)

하늘을닮은호수M 2005. 6. 13. 21:22
반응형

GNU Make

재컴파일을 지휘하는 프로그램(A Program for Directing Recompilation)

http://www.viper.pe.kr/docs/make-ko/make-ko_toc.html

GNU make Version 3.77.


May 1998

번역시작: March 2000

최종 갱신: May 9th, 2000

Richard M. Stallman 그리고 Roland McGrath
역자: 선정필

_make 개관(Overview of make)
make 유틸리티 커다란 프로그램의 어떤 조각들이 재컴파일되야 하는지를 자동으로 결정하고 그것들을 재컴파일하는 명령들을 발행한다. 이 매뉴얼은 GNU make를 설명한다. GNU make는 리차드 스톨만(Richard Stallman)과 롤랜드 맥그래스(Roland McGrath)에 의해서 개발되었다. GNU make는 IEEE Standard 1003.2-1992 (POSIX.2). 의 section 6.2와 호환된다.

우리의 예제들은 C 프로그램들을 보여줄 것이다. 이것이 가장 일반적이기 때문이지만 여러분은 어떤 프로그램 언어라도 그것의 컴파일러가 쉘 명령으로 실행될 수 있다면 make를 사용할 수 있다.

make를 사용하기 위해서 준비하려면 여러분은 여러분의 프로그램 안에 있는 파일들 간의 관계를 설명하고, 각 파일을 업데이트하는 명령들을 제공하는 makefile이라고 불리는 파일을 반드시 작성해야 한다. 전형적으로 프로그램 안에서 실행 파일은, 소스 파일들을 컴파일해서 만들어지는 오브젝트 파일들로부터 업데이트된다.

일단 적당한 makefile이 존재하면 여러분이 어떤 소스 파일들을 변경할 때마다 다음과 같은 쉘 명령이 모든 필요한 재컴파일들을 수행하는 데 충분하다:

make

make 프로그램makefile 데이터베이스파일들의 마지막-변경 시간들을 사용해서 어떤 파일들이 업데이트되어야 하는지를 결정한다. 이런 파일들 각각에 대해서 데이터베이스에 기록된 명령들을 수행한다.

어떤 파일들이 재컴파일되어야 하는지 또는 어떻게 재컴파일되어야 하는지를 제어하기 위해서, 여러분은 make에 대한 명령 라인 매개변수들을 제공할 수 있다. See section make 실행 방법(How to Run make).

__이 매뉴얼을 읽는 방법(How to Read This Manual)
여러분이 make의 초심자이거나 일반적인 설명을 찾고 있는 사람이라면 각 장의 나중 섹션들은 건너 뛰고 첫번째 몇 섹션들을 읽어라. 각 장에서 첫번째 몇가지 섹션들은 개론적인 또는 일반적인 정보들을 담고 있고 나중의 섹션들은 특수한 또는 기술적인 정보들을 담고 있다. 2장은 예외인 데, section Makefile 소개(An Introduction to Makefiles), 모든 것들이 개론적이다.

다른 make 프로그램들에 친숙하다면, GNU make가 갖고 있는 개선점들을 설명한 section GNU make의 기능과, 다른 것들이 가지고 있지만 GNU make는 갖고 있지 않는 몇가지 것들에 대한 설명을 한 section 비호환성과 빠진 기능들(Incompatibilities and Missing Features)을 보기 바란다.

빠른 요약을 위해서는 section 옵션들의 요약(Summary of Options), section 빠른 레퍼런스(Quick Reference), 그리고 section 특수 내장 타겟 이름(Special Built-in Target Names)을 보기 바란다.

__문제점과 버그(Problems and Bugs)

GNU make에 문제를 발견하였거나 버그를 발견했다면 그것을 개발자들에게 알려 주기 바란다; 우리는 우리가 그것을 고치기를 원한다는 것외에는 아무것도 약속할 수 있는 것이 없다.

버그를 리포트하기 전에 실제 버그를 실제로 발견했는지 확인하기 바란다. 조심스럽게 문서들을 다시 읽고 그리고 그것이 여러분이 하고자 하는 것을 할 수 있다고 실제로 말하는지 보기 바란다. 여러분이 어떤 것을 할 수 있는지 없는지 잘 모르겠다면 그것도 같이 보고해주기 바란다; 그것은 문서의 버그인 것이다!

버그를 리포트하기 전에 그리고, 그것을 여러분 스스로 고치도록 노력하기 전에, 그것을 그 문제를 다시 만드는 가능한 한 가장 작은 makefile로 분리해도록 해보라. 그리고 나서 그 makefile과 make가 여러분에게 만들어 내는 정확한 결과들을 우리에게 보내기 바란다. 또한 여러분이 일어날 것이라고 기대하는 것을 말해주기 바란다; 이것은 우리가 그 문제가 실제로 문서에 있는 것인지를 결정할 수 있도록 도울 것이다.

일단 여러분이 정확한 문제를 얻었다면 다음 주소로 이메일로 보내주기 바란다:

bug-make@gnu.org

여러분이 사용하는 make의 버전번호를 포함시켜 주기 바란다. 여러분은 이 정보를 `make --version'이라는 명령으로 얻을 수 있다. 또한 여러분이 사용중인 머쉰과 운영체제의 종류를 포함시켜 주기 바란다. 가능하다면 configuration 과정 중에 생성된 `config.h'라는 파일의 내용도 포함시켜 주기 바란다.

_Makefile 소개(An Introduction to Makefiles)
여러분은 makefile이라고 불리는, make에게 무엇을 할 것인가를 말하는, 파일이 필요하다. 대개 makefile은 make에게 어떤 프로그램을 컴파일하고 링크하는 방법을 설명한다.

이 장에서 우리는 8개의 C 소스 파일들과 3개의 헤더 파일들로 이루어진 텍스트 에디터를 컴파일하고 링크하는 방법을 기술하는, 단순한 makefile에 대해서 얘기할 것이다. makefile은 또한 make에게, 명시적으로 요구되었을 때 다양한 명령들을 실행하는 방법을 말할 수 있다(예를 들어서 어떤 파일들을 청소 작업으로써 제거하기). makefile의 좀 더 복잡한 예제를 보려면 section 복잡한 makefile 예제(Complex Makefile Example)을 참조하기 바란다.

make가 에디터를 재컴파일할 때 각 변경된 C 소스 파일들은 반드시 재컴파일되어야 한다. 헤더 파일이 변경되면, 해당 헤더 파일을 include하는 각 C 소스파일도 반드시 재컴파일되어야 한다. 각 컴파일은 소스 파일에 대응하는 오브젝트 파일을 생성한다. 마지막으로 어떤 소스 파일이 재컴파일되었다면, 모든 오브젝트 파일들은 그들이 새로 만들어진 것이든 아니든 반드시 같이 링크되어서 새로운 편집기 실행 파일을 만들어야 한다.

__규칙의 모습(What a Rule Looks Like)

단순한 makefile은 다음과 같은 모양의 "규칙들"로 이루어진다:


target ... : dependencies ...
command
...
...

target은 일반적으로 프로그램에 의해서 생성되는 파일의 이름이다; 실행 파일이나 오브젝트 파일 등이 target 파일의 예이다. target은 또한, `clean' (see section 가짜 목적물(Phony Targets))와 같은, 실행할 액션의 이름이 될 수도 있다.

dependency는 target을 만들기 위한 입력으로 사용되는 파일이다. target은 종종 여러개의 파일에 의존한다.

command는 make가 실행하는 액션이다. 규칙은 하나 이상의 command를 가질수도 있는 데, 각각은 자신의 라인 위에 있다. Please note: 여러분은 모든 command 라인의 처음에 하나의 탭 문자를 가져야 한다! 이것은 조심성 없음을 잡는 방해물이다.

일반적으로 command는 dependencies와 함께 한 규칙 안에 존재하고 dependencies들 중의 어떤 것이라도 변했다면 target 파일을 생성하는 일을 한다. 그러나, target을 위한 command들을 지정하는 규칙이 반드시 dependencies를 가질 필요는 없다. 예를 들어서 `clean'이라는 target과 연관된 삭제 command를 담고 있는 규칙은 dependencies를 가지지 않는다.

그렇다면 rule은 특정한 규칙의 target인 어떤 파일들을 언제 어떻게 리메이크할 것인가를 설명하는 것이 될 것이다. make는 target을 생성하거나 업데이트하기 위해서 dependencies에 command를 수행한다. 규칙은 또한 어떤 액션을 언제 어떻게 수행할 것인가를 설명할 수 있다.See section 규칙 작성(Writing Rules).

makefile은 규칙들 외에 다른 텍스트들을 담고 있을 수 있지만 단순한 makefile은 단지 규칙들을 담고 있을 뿐이다. 규칙들은 이런 템플리트에서 보여지는 것보다 어쩌면 좀 더 복잡해 보일 수 있지만, 모두가 이 패턴에 큰 오차없이 맞아 떨어진다.

__단순한 Makefile(A Simple Makefile)

여기에 edit 라고 불리는 실행 파일 하나가, 8개의 C 소스와 3개의 헤더 파일들에 의존하는, 8개의 오브젝트 파일들에 의존하는 모습을 설명한 직설적인 makefile 예제가 있다.

이 예제에서 모든 C 파일들은 `defs.h'을 include하지만 편집 명령들을 정의한 것들만이 `command.h'를 include하고 편집기 버퍼를 변경하는 낮은 레벨의 파일들만이 `buffer.h'를 include한다.

edit : main.o kbd.o command.o display.o

insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o

insert.o search.o files.o utils.o

main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c


clean :
rm edit main.o kbd.o command.o display.o

insert.o search.o files.o utils.o

우리는 기다란 라인을 백슬래시-개행을 사용해서 두 라인으로 분할했다; 이것은 하나의 긴 라인을 쓰는 것과 동일하지만 읽기에 더 쉬운 것이다.

이 `edit'라고 불리는 실행 파일을 만들도록 makefile을 쓰기 위해서는 다음과 같이 입력한다:

make

이 makefile을 사용해서 실행 파일과 모든 오브젝트 파일들을 삭제하려면 다음과 같이 입력한다:

make clean

이 예제 makefile에서 target들은 `edit'라는 실행 파일과 `main.o'와 `kbd.o'라는 오브젝트 파일들을 포함한다. dependencies는 `main.c'와 `defs.h'와 같은 파일들이다. 실제로 각 `.o' 파일은 target이면서 동시에 dependency이다. command는 `cc -c main.c'와 `cc -c kbd.c'를 포함한다/

target이 파일일 때, 어떤 dependencies 들중 하나가 변경되었을 때 재컴파일되거나 재링크되어야 한다. 게다가 스스로 자동적으로 생성된 어떤 dependencies는 맨먼저 업데이트되어야 한다. 이 예제에서 `edit'는 8개의 오브젝트 파일들에 의존한다; `main.o'는 소스 파일 `main.c'와 헤더 파일 `defs.h'에 의존한다.

target과 dependencies을 담고 있는 각 라인 뒤에 쉘 명령이 따른다. 이런 쉘 명령들은 target 파일을 업데이트 하는 방법을 말하는 것이다. 탭 문자 하나가 각 명령 라인의 맨 앞에, makefile의 다른 라인들과 명령 라인들 간의 구분이 되도록, 반드시 와야 한다. (make는 command가 어떻게 작옹하는지에 대해서 아무것도 모른다는 것을 기억하기 바란다. target 파일을 적절하게 업데이트할 명령들을 제공하는 것은 여러분들에게 달려 있다. target 파일이 업데이트되어야 할 때 여러분이 지정한 규칙들에 있는 command들을 실행하는 것이 `make'가 하는 모든 것이다.)

`clean'이라는 target은 파일이 아니고 단지 액션의 이름이다. 이 규칙안에 있는 액션이 일반적인 경우에 실행되는 것을 바라지 않을 것이기 때문에 이 규칙은 자신 스스로가 dependency가 아닐뿐더러 어떤 dependencies도 가지지 않는다. 그래서 이 규칙의 단 하나의 목적은 특정 명령들을 실행하는 것이다. 파일이 아닌 단지 액션을 지칭하는 targetphony targets이라고 불린다. 이런 종류의 target에 대한 정보를 보려면 See section 가짜 목적물(Phony Targets)을 참조하기 바란다. make가 rm이나 다른 명령으로부터 에러를 무시하도록 하는 방법에 대해서는 See section 명령에서 에러(Errors in Commands)를 참조하기 바란다.

__make가 Makefile를 처리하는 방법(How make Processes a Makefile)

디폴트로 make는 첫번째 target(그것의 이름이 `.'으로 시작하지 않는 target)으로 시작한다. 이것은 default goal이라고 불리는 것이다.(Goals는 make가 궁극적으로 업데이트하려고 하는 target이다 See section goal을 지정하는 매개변수(Arguments to Specify the Goals).)

이전 섹션에 있는 단순 예제에서 default goal은 실행 프로그램 `edit'를 업데이트하는 것이다; 그래서 우리는 그 규칙을 맨 처음에 놓았던 것이다.

그래서 다음과 같이 명령을 주면 make는 현재 디렉토리에서 makefile을 읽고 첫번째 규칙을 처리하기 시작한다:

make

예제에서 이 규칙은 `edit'를 리링킹하는 것이다; 그러나 make가 이 규칙을 완전히 처리할 수 있기 전에, `edit'가 의존하고 있는 파일들에 대한 규칙들을 반드시 처리해야 한다. 이것은 이경우 오브젝트 파일들이다. 이런 파일들 각각은 그 자신의 규칙에 따라서 처리된다. 이런 규칙들은 각 `.o'파일을 그의 소스 파일을 컴파일해서 업데이트하라고 말한다. 소스 파일이 또는 dependencies에 있는 헤더파일들 중 어떤 것이라도 오브젝트 파일보다 더 최근의 것이라면 또는 오브젝트 파일이 존재하지 않는다면 재컴파일이 반드시 일어나야 한다.

다른 규칙들은, 그들의 target들이 goal의 dependencies로 나타나기 때문에, 처리된다. 어떤 다른 규칙이 goal이 의존하는 것이 아니라면(또는 그것이 의존하는 어떤 것도 없다면), make에게 그렇게 하라고 말하지(make clean과 같은 명령으로) 않는 한, 그 규칙은 처리되지 않는다.

오브젝트 파일을 재컴파일하기 전에, make는 그것의 dependencies, 소스 파일과 헤더 파일들을 업데이트하는 것을 고민한다. 이 makefile은 그것들을 위해서 행해진 어떤 것도 지정하지 않은 것이다-- `.c'와 `.h'파일들은 어떤 규칙들의 target도 아니다-- 그래서 make는 이런 파일들에 대해서 아무것도 하지 않는다. 그러나 make는 Bison이나 Yacc에 의해서 만들어진 것들과 같은, C 프로그램들을, 이 순간 그들의 규칙에 의해서 자동으로 생성한다.

오브젝트 파일들이 필요로 하는 것이면 무엇이든 재컴파일한 후, make는 `edit'를 리링크할 것인가를 결정한다. 이것은, `edit'파일이 존재하지 않거나 오브젝트 파일들 중 어떤 것이라도 그것보다 더 최근의 것이라면, 반드시 수행되어야 한다. 어떤 오브젝트 파일이 단지 재컴파일되었다면 그것은 이제 `edit'보다 더 새로운 것이고 그래서 `edit'는 재링크된다.

그래서, 우리가 `insert.c' 를 변경하고 make를 실행하면, make는 `insert.o'를 갱신하기 위해서 그 파일을 컴파일할 것이고 `edit'를 링크할 것이다. 우리가 `command.h' 를 변경하고 make를 실행하면 make는 `kbd.o', `command.o' 그리고 `files.o'들을 재컴파일할 것이고 그리고 나서 `edit'를 링크할 것이다.

__Makefile을 좀 더 쉽게 만드는 변수들(Variables Make Makefiles Simpler)

우리의 예제에서 `edit'를 위한 규칙에서 우리는 모든 오브젝트 파일들을 두번씩 기술했다 (여기에 반복되어 있다):

edit : main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o
insert.o search.o files.o utils.o

이렇게 반복하는 것은 에러를 발생시킬 수 있는 여지가 있다; 새로운 오브젝트 파일이 시스템에 추가되면 우리는 그것을 한 리스트에는 추가하지만 다른 것에는 잊어 버리고 추가하지 않을 수 있다. 우리는 어떤 변수를 사용하여 이런 리스크를 없애고 makefile을 단순하게 만들 수 있다. Variables는 한번 정의되고 나중에 여러곳에서 대입되는 텍스트 문자열을 허락한다(see section 변수 사용 방법(How to Use Variables)).

모든 makefile이, 모든 오브젝트 파일 이름들의 리스트에 대해서 objects, OBJECTS, objs, OBJS, obj, 또는 OBJ 라는 이름의 변수를 쓰는 것은 표준 관례(standard practice)이다. 우리는 다음과 같은 makefile에서 처럼 그런 변수 objects를 하나의 라인으로 정의할 것이다:

objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o

그리고 나서 우리가 오브젝트 파일 이름들의 리스트를 놓고자 하는 곳마다 그 변수의 값을, `$(objects)'라고 써서 대입할 수 있다(see section 변수 사용 방법(How to Use Variables)).

오브젝트 파일들에 대한 변수를 사용할 때 단순한 makefile이 어떻게 보이는지에 대한 예시가 있다:

objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)


main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c


clean :
rm edit $(objects)

__`make'가 명령을 추론하도록 하기(Letting make Deduce the Commands)

개별 C 소스 파일들을 컴파일하기 위한 명령들을 전부 나열하는 것은 불필요하다. 왜냐면 make는 그것을 추측해낼 수 있기 때문이다: 그것은 `cc -c'명령을 사용해서 대응되는 `.c'파일로부터 `.o'파일을 갱신하기 위한 implicit rule을 가지고 있다. 예를 들어서, `main.c'를 `main.o'로 컴파일하기 위해서 `cc -c main.c -o main.o'라는 명령을 사용할 것이다. 그러므로 우리는 그 오브젝트 파일들에 대한 규칙들로부터 그 명령들을 생략할 수 있다. See section 묵시적 규칙(Using Implicit Rules).

`.c'파일이 이런 식으로 자동으로 사용될 때, 그것은 또한 dependencies 리스트에 자동으로 추가된다. 그러므로 우리는, 우리가 그 명령들을 생략했다면, dependencies로부터 `.c'파일들을 생략할 수 있다.

이런 변화들과 위에서 제시된 것과 같은 변수 objects 를 모두 예시한 다음 예제를 보자:

objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h

.PHONY : clean
clean :
-rm edit $(objects)

이것은 우리가 실제 상황에서 makefile을 작성하는 방법이다. (`clean'과 연관된 복잡함은 다른 곳에 기술되었다. section 가짜 목적물(Phony Targets), and section 명령에서 에러(Errors in Commands), 참조.)

묵시적 규칙은 아주 편리하기 때문에 중요하다. 여러분은 자주 사용되는 그것들을 볼 것이다.

__Makefile의 다른 스타일(Another Style of Makefile)

makefile의 오브젝트들이 단지 묵시적 규칙에 의해서만 생성된다면 makefile의 다른 대체 스타일이 가능해진다. 이런 makefile 스타일에서 여러분은 그들의 target들에 의해서가 아니라 그들의 dependencies에 의해서 엔트리들을 그룹 짓는다. 여기에 비슷하게 보이는 예제가 있다:

objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o

edit : $(objects)
cc -o edit $(objects)

$(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o : buffer.h

여기서 `defs.h'는 모든 오브젝트 파일들의 dependency로 주어졌다; `command.h'와 `buffer.h'는 그것들을 위해서 리스트된 특정 오브젝트 파일들의 dependencies이다.

이것이 더 나은가 아닌가는 취향의 문제이다: 이것이 좀 더 컴팩트하지만 어떤 사람들은 이것을, 그들이 한자리에 각 target에 대한 정보 모두를 넣는 것이 좀 더 분명하다고 생각하기 때문에, 싫어 한다.

__디렉토리를 청소하는 규칙(Rules for Cleaning the Directory)

어떤 프로그램을 컴파일하는 것이 여러분이 규칙을 쓰고자 하는 유일한 목적은 아니다. makefile들은 프로그램 하나를 컴파일하는 것 외에 몇 가지 다른 일들을 하는 방법을 보통 얘기한다: 예를 들어서 디렉토리가 `clean'되도록 모든 오브젝트 파일들과 실행 파일들을 지우는 방법.

여기에 우리의 예제 editor를 청소하는 make 규칙을 어떻게 쓸 수 있는가에 대한 예제가 있다:

clean:
rm edit $(objects)

실제로 우리는 예견하지 못한 상황들을 처리하기 위해서 어쩌면 좀 더 복잡한 방법으로 규칙을 쓰려고 할련지도 모른다. 우리는 이것을 할 것이다:

.PHONY : clean
clean :
-rm edit $(objects)

이것은 make가 `clean'이라고 불리는 실제 파일에 의해서 혼동되어지는 것을 막고 rm으로부터의 에러들에도 불구하고 그것이 계속되도록 한다. (section 가짜 목적물(Phony Targets), section 명령에서 에러(Errors in Commands), 참조)

이것과 같은 규칙은 makefile의 맨처음에 위치하면 안된다. 왜냐면 우리는 그것이 디폴트로 실행되기를 원하지 않기 때문이다! 그래서, makefile 예제에서 우리는, 그 에디터를 재컴파일하는, edit에 대한 규칙이 default goal로 남아있기를 원한다.

clean이 edit의 dependency가 아니기 때문에, 이 규칙은 우리가 `make'명령에게 매개변수를 주지 않는다면, 전혀 실행되지 않을 것이다. 이 규칙이 실행되도록 하기 위해서는 `make clean'이라고 입력해야 한다. See section make 실행 방법(How to Run make).

_Makefiles 작성(Writing Makefiles)
make에게 makefile이라고 불리는 데이터베이스를 읽어서 그것으로부터 시스템을 재컴파일 하는 방법을 가르켜 주는 정보.

__Makefile이 담고 있는 것(What Makefiles Contain)
makefile들은 다섯 가지 종류의 것들을 담고 있다: explicit rules, implicit rules, variable definitions, directives, 그리고 comments. 규칙, 변수, 그리고 지시자 등은 이 후 장들에서 설명될 것이다.

explicit rule 이 규칙의 목적물(target)이라고 불리는, 하나 이상의 파일들을 언제 어떻게 리메이크해야 하는지를 말하는

이다. 이것은 목적물이 depend on 다른 파일들 목록을 갖고 있으며 그 목적물들을 갱신하거나 생성하기 위해서 사용되

는 명령들을 갖고 있을 수도 있다. See section 규칙 작성(Writing Rules).

implicit rule은 그들의 이름에 기초한 어떤 파일들의 클래스를 언제 어떻게 리메이크할 것인가를 말하는 것이다. 이것

은,목적물이 이 목적물과 비슷한 이름을 갖는 파일에 의존할 수 있는 방법을 설명하고 그런 목적물을 갱신하고 생성하기

위한 명령들을 준다. See section 묵시적 규칙(Using Implicit Rules).
variable definition는, 나중에 텍스트로 대입될 수 있는 변수에 텍스트 문자열을 지정하는 라인이다. 단순 makefile 예제는

모든 오브젝트 파일들의 리스트로써 objects라는 변수 정의를 보여준다 (see section Makefile을 좀 더 쉽게 만드는 변수

들(Variables Make Makefiles Simpler)).
directive는 make가 makefile을 읽으면서 특별한 어떤 것을 하도록 하는 명령이다. 이들은 다음과 같은 것들을 포함한다:
◇ 다른 makefile을 읽는다 (see section 다른 makefile 삽입(Including Other Makefiles)).
◇ makefile의 일부를 사용할 것인가 아니면 무시할 것인가를 결정한다 (see section Makefile의 조건 부분(Conditional

Parts of Makefiles)).
◇ 여러 라인들을 포함하는 verbatim 문자열로부터 하나의 변수를 정의(see section 축어 변수 정의(Defining Variables

Verbatim)).
`#'comment을 시작한다. 그것과 해당 라인의 나머지 부분은 무시된다. 다른 backslash에 의해서 escape되지 않는 꼬

리 backslash는 주석을 여러 라인들에 걸쳐 계속되게 할 것이다. makefile에서 주석은 라인의 어느 곳에서나 나타날 수

있지만, define지시어나 그리고 아마도 명령들 안에서는 예외이다(쉘이 주석이라고 판단하는 곳). 주석만을 갖고 있는

(아마 그 앞에 공백들 몇개 있는) 라인은 블랭크이고 무시된다.

__여러분의 Makefile에 줄 이름(What Name to Give Your Makefile)

make가 makefile을 찾을 때, 이것은 디폴트로 다음과 같은 이름들을 순서대로 찾으려고 한다: `GNUmakefile', `makefile' 그리고 `Makefile'.

일반적으로 여러분은 여러분의 makefile을 `makefile'이나 `Makefile'로 불러야 할 것이다. (우리는 `Makefile'을 권한다. 왜냐면 그것이 디렉토리 리스팅의 처음 근처에, 다른 `README'와 같은 중요한 파일들 바로 근처에, 우뚝 솟아 보이기 때문이다.) 맨처음 검사되는 파일 `GNUmakefile'은 대부분의 makefile들에 대해서 추천되지 않는 것이다. 여러분은 이 이름을 GNU make에 종속적인 makefile에 대해서만 사용하기 바란다. 그리고 이 이름은 다른 make에 의해서 이해되지 않을 것이다. 다른 make 프로그램들은 `makefile'과 `Makefile' 을 찾지만 `GNUmakefile'은 찾지 않는다.

make가 이런 이름들 중에 어떤 것도 찾지 못하면 어떤 makefile도 사용하지 않는다. 이런 경우 여러분은 명령 매개변수로 어떤 goal을 반드시 지정해야 하고 그러면 make는 그것을 단지 내장된 묵지적 규칙들만을 사용하여서 리메이크하는 방법을 찾아낼 것이다. See section 묵시적 규칙(Using Implicit Rules).

여러분이 makefile에 대해서 비표준 이름을 사용하고자 한다면 makefile 이름을 `-f' 나 `--file'옵션을 사용해서 지정할 수 있다. 매개 변수들 `-f name'나 `--file=name' 은 make에게 makefile로써 name이라는 파일을 읽도록 한다. 하나 이상의 `-f name'나 `--file=name'옵션을 사용하면 여러가지 makefile들을 지정할 수 있다. 모든 makefile들이 지정된 순서대로 연결된다. 디폴트 makefile 이름들, `GNUmakefile',`makefile' 그리고 `Makefile'는 여러분이 `-f name'나 `--file=name'을 지정하면 자동으로 체크되지 않는다.

__다른 makefile 삽입(Including Other Makefiles)

include 지시어는 make가 현재 makefile을 읽는 것을 잠시 중단하고 계속하기 전에 하나 이상의 다른 makefile들을 읽도록 한다. 이 지시어는 다음과 같이 보이는 makefiel의 한 라인이다:

include filenames...

filenames can contain shell file name patterns.

그 라인의 여분의 공백들은 허용되고 무시되지만, 탭은 허용되지 않는다. (탭으로 그 라인이 시작하면 이것은 명령 라인으로 생각될 것이다.) include와 파일 이름들 사이에 그리고 파일 각각의 이름들 사이에 공백이 필요하다. `#'로 시작하는 주석이 라인의 마지막에 쓰여도 된다. 파일 이름들이 변수나 함수 레퍼런스를 담고 있다면 그들은 확장된다. See section 변수 사용 방법(How to Use Variables).

예를 들어서 여러분이 세 개의 `.mk' 파일들, `a.mk', `b.mk', 그리고 `c.mk'를 가지고 있고, $(bar)가 bish bash로 확장된다면 다음 표현은

include foo *.mk $(bar)

다음의 것과 동일하다.

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

make가 include 지시어를 처리하고 있을 때, 그것은 makefile을 담고 있는 것을 읽는 것을 잠시 중지하고 리스트된 파일들을 순서대로 읽는다. 이것이 끝나면 make는 지시어가 있었던 makefile을 다시 읽는다.

여러가지 디렉토리들에 있는 개개의 makefile들에 의해서 처리되는 다수의 프로그램들이 변수 정의들(see section 변수 설정(Setting Variables))이나 패턴 규칙들(see section 패턴 규칙을 정의하고 재정하기(Defining and Redefining Pattern Rules))의 공통 집합을 필요로 할 때가, include 지시어들을 사용하는 한가지 경우이다.

소스 파일들로부터 dependencies를 자동으로 생성하고자 할 때가 다른 그러한 경우이다; dependencies는 주(主) makefile에 의해서 삽입되는 파일에 놓여질 수 있다. 다른 버전의 make와 같이 전통적으로 행해진 것처럼 주 makefile의 마지막에다 dependencies를 추가하는 것보다, 저렇게 하는 것이 훨씬 더 분명하다. See section 종속물들을 자동으로 생성하기(Generating Dependencies Automatically).

지정된 이름이 slash로 시작하지 않고 그 파일이 현재 디렉토리에 없으면 다른 여러 디렉토리들이 검색된다. 먼저, `-I' 또는 `--include-dir' 옵션으로 지정한 임의의 디렉토리들이 검색된다(see section 옵션들의 요약(Summary of Options)). 그리고 나서 다음과 같은 디렉토리들이 이 순서로 (존재한다면) 검색된다: `prefix/include' (일반적으로 `/usr/local/include' (1)) `/usr/gnu/include', `/usr/local/include', `/usr/include'.

삽입된 makefile이 이런 디렉토리들중의 어느 곳에도 찾아질 수 없다면 경고 메시지가 나타나지만 이것은 즉각 치명적인 에러가 아니다; include를 포함하는 makefile의 처리가 계속된다. 일단 makefile들을 읽는 것이 끝나면 `make'는 갱신되어야 하는 것이나 존재하지 않는 것을 리메이크하려고 노력 할 것이다. See section Makefiles가 다시 만들어지는 과정(How Makefiles Are Remade). makefile을 리메이크하는 방법을 찾으려고 노력한 후에 그것이 실패한 경우에만 make는 makefile이 없는 것이 치명적인 에러라고 진단할 것이다.

make가 존재하지 않고 다시 만들어질 수 없는 makefile을 에러 메시지 없이 무시하도록 하고자 한다면 -include 지시어를 다음과 같이 include대신 사용하라:

-include filenames...

이것은 filenames에 있는 어떤 것이 존재하지 않더라도 에러가 없다는 것(경고조차도 없다)을 제외하고는 모든 면에서 include와 동일하게 작동한다. 다른 어떤 make 구현물들과 호환성을 위해서 -include'에 대한 다른 이름 sinclude이 제공된다.

__MAKEFILES 변수(The Variable MAKEFILES)

MAKEFILES 환경변수 이 정의되어 있다면,는 그것의 값을, 다른 것들 이전에 읽어야 하는 추가의 makefile 이름들(공백 문자로 분리된) 리스트로써 생각한다. 이것은 include와 아주 비슷하게 작동한다: 여러 디렉토리들이 그런 파일들에 대해서 검색된다(see section 다른 makefile 삽입(Including Other Makefiles)). 나아가 디폴트 목표는 이런 makefile들 중의 하나로부터 절대 얻어지지 않으며 MAKEFILES에 리스트된 파일들이 없어도 에러가 아니다. If the environment variable MAKEFILES is defined, make

MAKEFILES은 `make'의 재귀적인 호출 사이의 통신에서 주로 사용된다(see section make의 재귀적 사용(Recursive Use of make)). make의 톱-레벨 호출 이전에 이 환경변수를 설정하는 것은 일반적으로 권장되지 않는 것이다. 왜냐면 바깥으로부터 makefile을 혼합하지 않는 것이 일반적으로 더 좋기 때문이다. 그러나 make를 특정 makefile 없이 실행할 때, MAKEFILES에 있는 makefile은 검색 패스를 정의하는 것과 같은(see section 종속물을 위한 디렉토리 검색(Searching Directories for Dependencies))좀 더 잘 작동하는 내장 암시 규칙들을 돕는 유용한 일을 할 수 있다.

어떤 사용자들은 로그인할 때 자동으로 환경변수 안에다 MAKEFILES를 설정하여 프로그램 makefile들이 이렇게 되는 것을 기대하도록 하는 유혹을 받는다. 이것은 아주 나쁜 생각이다. 왜냐면 그런 makefile들은 다른 사람에 의해서 실행된다면 실패할 것이기 때문이다. 명시적인 include 디렉티브를 makefile 안에다 쓰는 것이 훨씬 더 좋다. See section 다른 makefile 삽입(Including Other Makefiles).

__Makefiles가 다시 만들어지는 과정(How Makefiles Are Remade)
어떤 경우 makefile은 RCS나 SCCS 파일들과 같은 다른 파일들에 의해서 다시 만들어질수 있다. makefile은 다른 파일로부터 다시 만들어질 수 있다면 여러분은 아마도 make가, 읽고 있는 makefile의 최근 버전을 획득하기를 원할 것이다.

이 때문에 모든 makefile들을 읽은 후에 make는 각각의 것을 목표 타겟으로 생각할 것이고 그것을 업데이트하려고 시도할 것이다. makefile이 그것(바로 그 makefile 안에서 아니면 다른 것에서 찾아지는)을 업데이트하는 방법을 말하는 규칙을 가지고 있거나 또는 묵시 규칙이 그것에 적용되는 것이라면(see section 묵시적 규칙(Using Implicit Rules)), (필요하다면) 업데이트될 것이다. 모든 makefile들이 체크된 후에 임의의 것이 실제로 변경되었다면 make는 깨끗한 상태에서 다시 시작해서 모든 makefile들을 다시 읽는다. (그들 각각을 다시 업데이트하려고 시도하겠지만 일반적으로 이것은 그들을 다시 변경하지 않을 것이다. 왜냐면 그들이 이미 업데이트되었기 때문이다.)

makefile들이 명령들은 있지만 종속물들이 없는, 파일을 리메이크할 더블-콜론 규칙을 지정하였다면 그 파일은 항상 다시 만들어질 것이다(see section 더블-콜론 규칙(Double-Colon Rules)). makefile의 이런 경우 명령들은 있지만 종속물들이 없는 더블-콜론을 가진 makefile은 make가 실행할 때마다 다시 만들어질 것이다. 그리고 make가 시작하고 makefile을 다시 읽은 후 반복할 것이다. 이것은 그래서 무한 루프를 발생한다: make는 항상 makefile을 다시 만들것이고 다른 것은 전혀 하지 않을 것이다. 그래서 이것을 피하기 위해서 make는 종속물이 없는 더블-콜론 타켓들로 지정된 makefile들을 다시 만들려고 하지 않을 것이다.

`-f'나 `--file'옵션들을 사용해서 읽을 makefile을 지정하지 않았다면 make는 디폴트 makefile 이름들을 시도할 것이다; see section 여러분의 Makefile에 줄 이름(What Name to Give Your Makefile). `-f'나 `--file'옵션들로 명시적으로 요구된 makefile들과는 달리 make는 이런 makefile들이 존재하는지 모른다. 그러나 디폴트 makefile이 존재하지 않지만 make 규칙들을 실행함으로써 생성될 수 있다면 여러분은 아마도 그 makefile이 사용될 수 있도록 실행될 규칙들을 원할 것이다.

그러므로 디폴트 makefile들 중 어떤 것도 존재하지 않는다면 make는 하나를 만들 때까지 또는 시도할 이름이 없을 때까지 그들이 검색되는 동일한 순서로 그들 중 하나를 만들려고 노력할 것이다(see section 여러분의 Makefile에 줄 이름(What Name to Give Your Makefile)) make가 makefile을 찾을 수 없거나 만들 수 없다는 것은 에러가 아님을 주목하자; makefile은 언제나 필요한 것은 아니다.

`-t'나 `--touch'옵션을 사용할 때 (see section 명령 실행 대신에...(Instead of Executing the Commands)),여러분은 어떤 타켓을 touch할 것인가를 결정하기 위해서 날짜가 지난 makefile을 사용하기를 원치 않을 것이다. 그래서 `-t' 옵션은 makefile들을 업데이트하는 효과가 없다; 그들은 실제로 `-t'가 지정되었다 하더라도 업데이트된다. 비슷하게, `-q' (또는 `--question')과 `-n' (또는 `--just-print') 옵션들은 makefile들의 업데이트를 금지하지 못한다. 왜냐면 out-of-date인 makefile은 다른 타겟들에 대해서 잘못된 결과를 낼 것이기 때문이다. 그래서 `make -f mfile -n foo'라고 하면 `mfile'을 업데이트하고 그것을 읽은 후 실행없이, `foo'와 그것의 종속물들을 업데이트하는 명령들을 디스플레이할 것이다. `foo'에 대해서 디스플레이된 명령들은 `mfile'의 업데이트된 내용안에서 지정된 것들이다.

그러나 때때로 여러분은 실제 makefile들의 갱신을 금지하고자 할런지도 모른다. 여러분은 이것을, makefile들을 명령라인에서 goal로 지정하고 동시에 그들을 makefile들로 지정해서, 할 수 있다. makefile 이름이 명시적으로 goal로써 지정될 때 `-t'과 기타 등등이 그것들에 적용된다.

그래서 `make -f mfile -n mfile foo'는 makefile인 `mfile'를 읽고서 실제로 명령들을 실행하지 않고 이것을 업데이트할 명령들을 디스플레이할 것이다. 그리고 나서 `foo'을 업데이트하는 데 필요한 명령들을 실제로는 실행하지 않고 디스플레이할 것이다. `foo'를 위한 명령들은 `mfile'의 현존하는 내용물에 의해서 지정된 것이 될 것이다.

__다른 Makefile의 일부를 오버라이딩(Overriding Part of Another Makefile)
때때로 다른 makefile과 거의 대부분 동일한 makefile을 가지는 것이 유용하다. 여러분은 종종 `include' 지시어를 사용해서 다른 makefile 안에다 makefile 하나를 포함시킬 수 있으며 그래서 더 많은 타겟이나 변수 정의를 포함할 수 있다. 그러나 두 makefile들이 동일한 타겟에 대해서 다른 명령들을 제공한다면 make는 여러분이 이것을 실행하도록 하지 않을 것이다. 그러나 다른 방법이 있다.

담고 있는 makefile(다른 것을 포함하고자 하는 것)안에서 여러분은 담고 있는 makefile에 있는 정보로부터 임의의 타겟을 다시 만들기 위해서 make는 반드시 다른 makefile을 보아야 한다는 것을 말하는 match-anything 패턴 규칙을 사용할 수 있다. 패턴 규칙에 대한 좀 더 많은 정보를 원한다면 See section 패턴 규칙을 정의하고 재정의하기(Defining and Redefining Pattern Rules)를 참조.

예를 들어서 타겟 `foo'(그리고 다른 타겟들)을 만드는 방법을 말하는 `Makefile'라고 불리는 makefile을 가지고 있다면 여러분은 다음과 같은 것을 담고 있는 `GNUmakefile'라는 이름의 makefile을 작성할 수 있다:

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'라는 종속물을 가지고 있도록 지정하고 있으며 이것은 타겟 파일이 이미 존재하더라도 명령들이 실행되도록 보장하기 위한 것이다. 우리는 make가 `force' 타겟을 빌드하기 위한 묵시적 규칙을 찾지 못하도록 금지하는, 빈 명령들을 주었다---그렇게 하지 않으면 `force' 자신에다 동일한 match-anything 규칙을 적용해서 종속물 루프를 만들것이다.

_규칙 작성(Writing Rules)

rule은 makefile에 나타나고 언제 그리고 어떻게 규칙의 targets(대개 하나의 규칙에 하나만 존재)이라고 불리는 어떤 파일들을 리메이크하는지를 지정한다. 이것은 목적물의 dependencies인 다른 파일들 리스트와 그 목적물을 생성하거나 갱신하는 데 사용될 "명령"을 담고 있다.

규칙들의 순서는, 디폴트 목표(default goal)을 결정하는 것을 제외하고는, 중요한 것이 아니다: 여기서 디폴트 목표(default goal이란 make가, 여러분이 아무것도 지정하지 않는 경우, 생각하는 타겟. 디폴트 목표는 첫번째 makefile의 첫번째 규칙의 타겟이다. 첫번째 규칙이 다수의 타겟들을 가지고 있으면 첫번째 타겟만이 디폴트로 취급된다. 그러나 두가지 예외들이 있다: 점으로 시작하는 타겟은 그것이 하나 이상의 슬래쉬, `/'를 담고 있지 않으면 디폴트가 아니다; 패턴 규칙을 정의하는 타겟은 디폴트 목표에 영향을 미치지 않는다. (See section 패턴 규칙을 정의하고 재정하기(Defining and Redefining Pattern Rules).)

그러므로 우리는 보통 첫번째 규칙이, 전체 프로그램 또는 makefile에 의해서 기술된 모든 프로그램들을 컴파일하는 것이 되도록, makefile을 작성한다(종종 `all'라는 이름의 타겟으로). See section goal을 지정하는 매개변수(Arguments to Specify the Goals).

__규칙 문법(Rule Syntax)
일반적으로 규칙은 다음과 같이 생겼다:

targets : dependencies
command
...

또는 다음과 같이 생겼다:

targets : dependencies ; command
command
...

targets은 공백으로 분리된 파일 이름들이다. 와일드카드 문자들이 사용될 수도 있으며(see section 파일 이름에 와일드카드 사용(Using Wildcard Characters in File Names)) `a(m)' 형태의 이름은 archive 파일a(see section 타겟으로써 아카이브 멤버(Archive Members as Targets)안에 있는 멤버 m을 표현한다. 일반적으로 규칙 하나당 하나의 타겟이 존재하지만 종종 좀 더 많은 타겟들을 가질 수도 있다(see section 하나의 규칙안의 다수의 타겟들(Multiple Targets in a Rule)).

command 라인들은 탭 문자로 시작한다. 첫번째 명령은 종속물 다음 라인에 탭 문자를 가진 라인으로 나타날 수도 있고 아니면 세미콜론을 가진 동일한 라인에 나타날 수 있다. 양쪽다 그 효과는 동일하다. See section 규칙내 명령 작성(Writing the Commands in Rules).

달러 기호들은 변수 참조를 시작하는 데 사용되기 때문에 여러분이 실제로 규칙에서 하나의 달러 기호를 쓰고자 한다면 달러 두개 `$$'를 반드시 써야 한다(see section 변수 사용 방법(How to Use Variables)). 여러분은 기다란 라인을 백슬레시 더하기 개행 문자를 넣어서 분할할 수 있지만 이것은 반드시 필요한 것이 아니다. 왜냐면 make가 makefile의 각 라인의 최대 길이를 제한하지 않기 때문이다.

규칙은 make에게 두가지 것을 말한다: 타겟들이 언제 out of date인가와 그것들을 필요할 때 어떻게 업데이트할 것인가를 말한다.

out of date인지 아닌지를 판단하는 기준은 DEPENDENCIES 라는 용어로 지정된다. 이것은 공백으로 분리되는 파일 이름들로 구성된다. (와일드카드들과 아카이브 멤버들(see section 아카이브 파일을 갱신하기 위해서 make 사용하기(Using make to Update Archive Files))도 여기서 역시 허용된다.) 타겟은 그것이 존재하지 않거나 종속물들중의 어떤것이라도 이것보다 더 오래된 것이라면 out of date이다(최종-변경 시간을 비교해서). 타겟 파일의 내용물은 종속물들의 정보에 기반을 두고 계산된다는 생각때문에 종속물들 중의 하나라도 변경되면 존재하는 타겟의 내용물은 더이상 유효한 것이 아니다.

업데이트하는 방법은 commands에 의해서 지정된다. 이들은 쉘에 의해

반응형