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


묵시적 규칙(Using Implicit Rules)

타겟 파일들을 리메이크하는 어떤 표준 방법들이 자주 사용된다. 예를 들어서 오브젝트 파일을 만드는 통상적인 방법은 C 소스로부터 C 컴파일러, cc를 사용하는 것이다.

묵시적 규칙(Implicit rules) 은 사용하고자 할 때 그것들을 자세하게 지정할 필요없도록, 통상적인 테크닉들을 사용하는 방법을 make 에게 말한다. 예를 들어서 C 컴파일을 위한 묵시적 규칙이 있다. 파일 이름들이 어떤 묵시적 규칙들이 실행될 것인가를 결정한다. 예를 들어서 C 컴파일은 `.c' 파일을 보통 취해서 `.o' 파일을 만든다. 그래서 make는 이것이 파일 이름의 끝부분들(확장자들)의 조합을 볼 때 C 컴파일을 위한 묵시적 규칙을 적용한다.

묵시적 규칙들의 연쇄고리가 순차적으로 적용될 수 있다; 예를 들어서, make`.y' 파일로부터 `.o' 파일을, `.c' 파일을 경유해서 리메이크할 것이다. See section 묵시적 규칙의 연쇄(Chains of Implicit Rules).

내장 묵시적 규칙들은, 변수들의 값들을 변경해서 여러분이 묵시적 규칙들이 작동하는 방식을 변경할 수 있도록, 그들의 명령에서 몇가지 변수들을 사용한다. 예를 들어서 변수 CFLAGS 는 C 컴파일을 위한 묵시적 규칙에 의해서 C 컴파일러에게 주어진 플래그들을 제어한다. See section 묵시적 규칙에 의해 사용되는 변수(Variables Used by Implicit Rules).

여러분 자신만의 묵시적 규칙들을 패턴 규칙들(pattern rules)를 작성함으로써 정의할 수 있다. See section 패턴 규칙을 정의하고 재정하기(Defining and Redefining Pattern Rules).

접미사 규칙(uffix rules) 은 묵시적 규칙들을 정의하는 좀 더 제한된 방식이다. 패턴 규칙들이 좀 더 일반적이고 명쾌한 것이지만 접미사 규칙들은 호환성을 위해서 아직 남아 있다. See section 구닥다리 접미사 규칙(Old-Fashioned Suffix Rules).

묵시적 규칙 사용(Using Implicit Rules)

make가 타겟 파일을 갱신하기 위한 관습적인 방법을 찾도록 하기 위해서 여러분이 해야 할 일은 명령들을 스스로 지정하지 않도록 하는 것이 전부이다. 명령 라인들이 없는 규칙을 작성하거나 그런 규칙을 전혀 작성하지 말자. 그러면 make는 사용할 묵시적 규칙을, 어떤 종류의 소스 파일이 존재하는가와 만들어질 수 있는가에 기반해서, 찾아낼 것이다.

예를 들어서 makefile이 다음과 같이 생겼다고 하자:

foo : foo.o bar.o
        cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

`foo.o'를 언급했지만 그것에 대한 규칙을 지정하지 않았기 때문에 make는 자동으로 그것을 갱신하는 방법을 말하는 묵시적 규칙을 찾을 것이다. 이것은 `foo.o'가 현재 존재하는지 안하는지에 상관없이 일어난다.

묵시적 규칙이 있으면 이것은 명령들과 하나 이상의 종속물들(소스 파일들) 모두를 공급할 수 있다. 묵시적 규칙이 공급할 수 없는, 헤더 파일들과 같은, 추가의 종속물들을 지정해야 한다면, `foo.o'에 대한 규칙을 명령 라인들이 없이 작성하고자 할 것이다.

각 묵시적 규칙은 하나의 타겟 패턴과 종속물 패턴들을 가진다. 동일한 타겟 패턴을 가지는 많은 묵시적 규칙들이 존재할 수 있다. 예를 들어서 많은 규칙들이 `.o' 파일들을 만들 수 있다: 하나는, `.c' 파일로부터 C 컴파일러를 사용할수도 있고; 다른 것은, `.p' 파일로부터 파스칼 컴파일러를 사용할 수도 있다; 기타 등등. 실제로 적용되는 규칙은 그것의 종속물이 존재하거나 만들어질 수 있는 것 하나이다. 그래서 파일 `foo.c'를 가진다면, make는 C 컴파일러를 실행할 것이다; 그렇지 않고 `foo.p'를 가진다면 make는 파스칼 컴파일러를 실행할 것이다; 기타 등등.

물론, makefile을 작성할 때 여러분은 make가 사용했으면 하는 묵시적 규칙이 어떤 것인가를 알고 있으며, 어떤 종속 파일들이 존재할 것인가를 알고 있기 때문에 make가 그것을 선택할 것이라는 것을 안다. 모든 사전에 정의된 묵시적 규칙들 카달로그를 보려면 See section 묵시적 규칙들의 카달로그(Catalogue of Implicit Rules).

위에서 우리는 하나의 묵시적 규칙이, 요구된 종속물들이 "존재하거나 만들어질 수 있으면" 적용된다고 말했다. 파일은 그것이 maekefile에서 타겟이나 종속물로 명시적으로 지정되고 묵시적 규칙이 그것을 만드는 방법을 재귀적으로 알아낼 수 있다면, "만들어질 수 있다". 묵시적 종속물이 다른 묵시적 규칙의 결과이라면 우리는 연쇄작용(chaining)이 일어났다고 말한다. See section 묵시적 규칙의 연쇄(Chains of Implicit Rules).

일반적으로 make는 각 타겟에 대해서 명령이 없는 묵시적규칙, 각 더블-콜론 규칙을 검색한다. 종속물로만 언급된 파일은, 타겟의 규칙이 아무것도 지정하지 않는 타겟으로 생각되고, 그래서 이것에 대한 묵시적 규칙이 검색된다. 검색이 이루어지는 방법에 대한 자세한 내용은 See section 묵시적 규칙 검색 알고리즘(Implicit Rule Search Algorithm).

명시적 종속물들은 묵시적 규칙 검색에 아무런 영향도 미치지 않는다는 점에 주목하자. 예를 들어서 다음과 같은 명시적 규칙을 생각하자:

foo.o: foo.p

`foo.p'의 종속성은 make가 오브젝트 파일 `.o' 파일에 대한 묵시적 규칙에 따라서 파스칼 소스 파일 `.p' 파일로부터 `foo.o'를 리메이크할 것이다라는 것을 반드시 의미하지 않는다. 예를 들어서 `foo.c'가 이미 존재하고 C 소스 파일로부터 오브젝트 파일을 만드는 묵시적 규칙이 대신 사용된다. 왜냐면 이것이 사전 정의된 묵시적 규칙들의 리스트에서 파스칼에 대한 규칙보다 먼저 나오기 때문이다 (see section 묵시적 규칙들의 카달로그(Catalogue of Implicit Rules)).

묵시적 규칙이 명령들이 없는 타겟에 대해서 사용되기를 원하지 않는다면 타겟에게, 하나의 세미콜론만 작성해서 빈 명령들을 줄 수 있다 (see section 빈 명령 사용하기(Using Empty Commands)).

묵시적 규칙들의 카달로그(Catalogue of Implicit Rules)

다음은 makefile이 이들을 명시적으로 오버라이드하거나 취소하지 않았다면 항상 사용이 가능한 사전에 정의된 묵시적 규칙들의 카달로그이다. 묵시적 규칙들을 취소하거나 오버라이드하는 정보에 대해서 See section 묵시적 규칙 취소시키기(Canceling Implicit Rules). `-r'이나 `--no-builtin-rules' 옵션은 모든 사전에 정의된 규칙들을 취소시킨다.

`-r' 옵션이 주어지지 않았다하더라도, 이들 규칙들 모두가 항상 정의되는 것은 아니다. 많은 사전에 정의된 규칙들은 make에서 접미사 규칙들로 구현된다. 그래서 이들은 접미사 리스트(suffix list)에 의존적으로 정의될 것이다 (특수한 타겟 .SUFFIXES의 종속물들의 리스트). 디폴트 접미사 리스트는 다음과 같다: .out, .a, .ln, .o, .c, .cc, .C, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el. 종속물들이 이런 접미사들 중의 하나를 가지는 아래에서 기술된 묵시적 규칙들 모두는 실제로 접미사 규칙들이다. 접미사 리스트를 변경한다면 단지 효력 있는 사전에 정의된 접미사 규칙들만이 여러분이 지정한 리스트에 있는 접미사들 중의 하나나 둘의 이름을 가지는 것들이 될 것이다; 접미사들 중에서 이들 리스트에 있지 않는 규칙들은 사용 불가능이 된다. 접미사 규칙들에 대한 상세한 내용은 See section 구닥다리 접미사 규칙(Old-Fashioned Suffix Rules).

C 프로그램 컴파일(Compiling C programs)
`n.o'`n.c' 로부터 `$(CC) -c $(CPPFLAGS) $(CFLAGS)' 형태의 명령에 의해서 자동으로 만들어진다.
C++ 프로그램 컴파일(Compiling C++ programs)
`n.o'`n.cc'`n.C' 로부터 `$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)' 형태의 명령에 의해서 자동으로 만들어진다. C++ 소스 파일들에 대해서 `.c' 대신에 `.cc' 접미사를 사용하기를 권한다.
파스칼 프로그램 컴파일(Compiling Pascal programs)
`n.o'`n.p' 로부터 `$(PC) -c $(PFLAGS)' 라는 명령을 사용해서 자동으로 만들어진다.
포트란과 Ratfor 프로그램 컴파일(Compiling Fortran and Ratfor programs)
`n.o'`n.r', `n.F' 또는 `n.f' 로부터 포트란 컴파일러를 실행해서 자동으로 만들어진다. 사용된 정확한 명령은 다음과 같다:
`.f'
`$(FC) -c $(FFLAGS)'.
`.F'
`$(FC) -c $(FFLAGS) $(CPPFLAGS)'.
`.r'
`$(FC) -c $(FFLAGS) $(RFLAGS)'.
포트란과 Ratfor 프로그램 사전처리(Preprocessing Fortran and Ratfor programs)
`n.f'`n.r' 또는 file{n.F} 로부터 자동으로 만들어진다. 이 규칙은 Ratfor 또는 사전처리가능한 포트란 프로그램을 엄격한 포트란 프로그램으로 변환하는 사전처리기를 실행시킬 뿐이다. 사용되는 정확한 명령은 다음과 같다:
`.F'
`$(FC) -F $(CPPFLAGS) $(FFLAGS)'.
`.r'
`$(FC) -F $(FFLAGS) $(RFLAGS)'.
Modula-2 프로그램 컴파일(Compiling Modula-2 programs)
`n.sym'`n.def' 로부터 `$(M2C) $(M2FLAGS) $(DEFFLAGS)' 라는 형태의 명령을 사용해서 만들어진다. `n.o'`n.mod';로부터 만들어진다. 그 형태는 다음과 같다: `$(M2C) $(M2FLAGS) $(MODFLAGS)'.
어셈블러 프로그램을 어셈블링하고 사전처리하기(Assembling and preprocessing assembler programs)
`n.o'`n.s' 로부터 어셈블러 as 를 실행함으로써 자동으로 만들어진다. 정확한 명령은 `$(AS) $(ASFLAGS)'. `n.s' 는 C 선행 처리기 cpp 를 실행함으로써 `n.S' 파일로부터 자동으로 만들어진다. 정확한 명령은 `$(CPP) $(CPPFLAGS)'.
단일 오브젝트 파일을 링크(Linking a single object file)
`n'`n.o' 로부터 C 컴파일러를 경유해서 링커(보통 ld)를 실행함으로써 자동으로 만들어진다. 정확한 명령은 `$(CC) $(LDFLAGS) n.o $(LOADLIBES)'. 이 규칙은 단일 소스 파일을 가지는 단순한 프로그램에 대해서 정확한 것을 한다. 다수의 오브젝트 파일들이 있더라도(아마도 다양한 다른 소스 파일들로부터 온 것) 정확한 것을 행할 것이다. 이들중 하나는 실행 파일의 이름과 같은 이름을 가진다. 그래서,
x: y.o z.o
`x.c', `y.c' 그리고 `z.c' 모두가 존재할 때 다음을 실행할 것이다:
cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o
좀 더 복잡한 경우, 이름이 실행 파일로부터 유도되는 오브젝트 파일이 없을 때, 링크를 위해서 명시적 명령을 작성해야 한다. `.o' 오브젝트 파일들로 만들어지는 각 종류의 파일은 컴파일러(`$(CC)', `$(FC)', 또는 `$(PC)' 를 사용해서 자동으로 링크된다; C 컴파일러 `$(CC)'`-c' 옵션 없이 `.s' 파일들을 어셈블하는 데 사용된다. 이것은 `.o' 오브젝트 파일들을 중간 파일들로 사용함으로써 이루어진다. 그러나 이것은 한 스텝으로 컴파일하고 링크하는 데 더 빠르다. 이것이 어떻게 이루어지는가이다.
C 프로그램을 Yacc(Yacc for C programs)
`n.c'`n.y'로 부터 `$(YACC) $(YFLAGS)' 라는 명려을 실행함으로써 자동으로 만들어진다.
C 프로그램을 Lex(Lex for C programs)
`n.c'`n.l' 로부터 Lex 를 실행함으로써 자동으로 만들어진다. 실제 명령은 `$(LEX) $(LFLAGS)'.
Ratfor 프로그램을 Lex(Lex for Ratfor programs)
`n.r' 는 Lex를 실행하여 `n.l' 로부터 자동으로 만들어진다. 실제 명령은 `$(LEX) $(LFLAGS)'. 동일한 접미사 `.l'을 모든 Lex 파일들에 대해서 사용하는 관례는, 그들이 Ratfor 코드나 C 코드들 중에 어떤 것을 만들던지 상관없이, make가 특별한 경우에 이 두 언어들 중의 어떤 것을 사용중인지 자동으로 결정하는 것을 불가능하게 만든다. `.l' 파일로부터 오브젝트 파일을 다시 만들기 위해서 make가 호출되었다면 이것은 어떤 컴파일러를 사용할 것인가를 반드시 추측해내야 한다. C 컴파일러라고 추측해낼 수도 있을 것이다. 왜냐면 이것이 가장 일반적이기 때문이다. Ratfor를 사용하고 있다면 make가 이것을 알도록 `n.r'을 makefile안에 언급해야 한다. 또는 Ratfor를 C 파일들 없이, 배타적으로 사용하고 있다면 다음과 같이 해서 묵시적 규칙 접미사 리스트로부터 `.c'를 제거하라:
.SUFFIXES:
.SUFFIXES: .o .r .f .l ...
C, Yacc, 또는 Lex 프로그램으로부터 Lint 라이브러리 만들기(Making Lint Libraries from C, Yacc, or Lex programs)
`n.ln'lint를 실행해서 `n.c' 로부터 만들어진다. 정확한 명령은 `$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i'. `n.y'`n.l' 로부터 만들어진 C 코드에 대해서 동일한 명령이 사용된다.
TeX 과 웹(TeX and Web)
`n.dvi'`n.tex' 로부터 `$(TEX)' 명령에 의해서 만들어진다. `n.tex'`n.web' 로부터 `$(WEAVE)' 로 만들어지거나, `n.w' 로부터 (그리고 `n.ch' 가 존재하거나 만들어질 수 있다면 이것으로부터) `$(CWEAVE)' 명령에 의해서 만들어진다. `n.p'`n.web' 로 부터 `$(TANGLE)' 명령에 의해서 만들어지고 `n.c'`n.w' 로부터(그리고 `n.ch' 이 존재하거나 만들어질 수 있다면 이것으로부터) `$(CTANGLE)' 명령에 의해서 만들어진다.
Texinfo 와 Info
`n.dvi'`n.texinfo', `n.texi', 또는 `n.txinfo' 로부터 `$(TEXI2DVI) $(TEXI2DVI_FLAGS)' 명령을 사용해서 만들어진다. `n.info'`n.texinfo', `n.texi', 또는 `n.txinfo' 로부터 `$(MAKEINFO) $(MAKEINFO_FLAGS)' 명령을 사용해서 만들어진다.
RCS
`n' 이라는 이름을 가진 임의의 파일은 `n,v' 또는 `RCS/n,v' 라는 이름을 가진 RCS 파일로부터, 필요하다면 추출된다. 사용되는 정확한 명령은 `$(CO) $(COFLAGS)' 이다. `n' 는 이것이 이미 존재하거나, 심지어 RCS 파일이 더 새로운 것이라 할 지라도, RCS 로부터 추출되지 않을 것이다. RCS 를 위한 규칙들은 제일 마지막(terminal) (see section 임의의 것과도 일치하는 패턴 규칙(Match-Anything Pattern Rules)) 이어서, RCS 파일들은 다른 소스들로부터 만들어질 수 없다; 그들은 실제로 반드시 존재해야 한다.
SCCS
`n'`s.n' 또는 `SCCS/s.n' 라는 이름을 가진 SCCS 파일로부터, 필요하다면 추출도니다. 사용되는 정확한 명령은 `$(GET) $(GFLAGS)' 이다. SCCS 를 위한 규칙들은 제일 마지막(terminal) (see section 임의의 것과도 일치하는 패턴 규칙(Match-Anything Pattern Rules)) 이이서, SCCS 파일들은 다른 소스로부터 만들어질 수 없다; 그들은 반드시 실제로 존재해야 한다. SCCS 을 위해서, `n' 이란 파일이 `n.sh' 라는 것으로부터 복사되고 실행 가능이 된다(모두에 의해서). 이것은 SCCS 에 체크인되는 쉘 스크립트이다. RCS 는 파일의 실행 퍼미션을 보존하기 때문에 이 기능을 RCS 와 함께 사용할 필요가 없다. 우리는 SCCS 를 되도록이면 사용하지 않도록 권고하는 바이다. RCS 는 널리 더 좋은 것이라고 생각되어지고 있고 또한 공짜이다. 비슷한(또는 더 못한) 상용 소프트웨어 대힌 무료 소프트웨어를 선택함으로써 여러분은 자유 소프트웨어 운동을 지원하는 것이다.

보통 위의 있는 테이블에 나온 변수들만을 변경하고자 할 것이다. 이들은 다음 섹션에서 설명된다.

그러나 내장 묵시 규칙들에 있는 명령들이 실제로 COMPILE.c, LINK.p, 그리고 PREPROCESS.S 와 같은 변수들을 사용한다. 이들의 값은 위에 나열된 명령들을 담고 있다.

make 는, `.x' 소스 파일을 컴파일하는 규칙은 COMPILE.x 라는 변수를 사용한다는 관례를 사용한다. 비슷하게 `.x' 라는 파일로부터 실행 파일ㅇ르 만드는 규칙은 LINK.x 를 사용한다; `.x' 를 선행 처리하는 규칙은 PREPROCESS.x 를 사용한다.

오브젝트 파일을 생성하는 모든 규칙들은 OUTPUT_OPTION 변수를 사용한다. make 는 이 변수를 컴파일 때의 옵션에 따라서, `-o $@'를 담도록, 또는 빈 것이 되도록 정의한다. VPATH (see section 종속물을 위한 디렉토리 검색(Searching Directories for Dependencies) 를 사용할 때와 비슷하게, 다른 디렉토리에 소스가 있을 때, 결과가 정확한 파일로 가도록 하기 위해서 `-o' 옵션을 사용할 필요가 있다. 그러나, 어떤 시스템들에서 컴파일러들은 오브젝트 파일들에 대해서 `-o' 옵션을 받아들이지 않는다. 그런 시스템을 사용하고 있다면, VPATH를 사용한다면, 어떤 컴파일은 그들의 결과를 다른 위치에다 놓을 것이다. 이런 문제에 대한 가능한 해결법(workaround)은 OUTPUT_OPTION 에게 `; mv $*.o $@' 값을 주는 것이다.

묵시적 규칙에 의해 사용되는 변수(Variables Used by Implicit Rules)

내장 묵시적 규칙의 명령들은 어떤 사전정의된 변수들을 자유롭게 사용한다. 이런 변수들을 makefile 안에서, make에 대한 매개변수들로, 또는 환경에서, 묵시적 규칙들을 재정의하지 않고서 이들이 작동하는 방식을 바꾸기 위해, 변경할 수 있다.

예를 들어서 C 소스 파일을 컴파일하는 데 사용되는 명령은 실제로 `$(CC) -c $(CFLAGS) $(CPPFLAGS)' 이다. 사용된 변수들의 실제 값들은 `cc'와 아무것도 아니기 때문에 결국 `cc -c' 이 된다. `CC'`ncc'로 재정의함으로써, `ncc' 가 묵시적 규칙에 의해서 수행되는 모든 C 컴파일에 대해서 사용되도록 할 수 있다. `CFLAGS'`-g' 로 변경해서 `-g' 옵션을 각 컴파일에 전달할 수 있다. C 컴파일을 수행하는 모든 묵시적 규칙들은 `$(CC)' 를 사용하여 그 컴파일러의 프로그램 이름과 모든 것이 컴파일러에게 주어진 매개변수들 안에 `$(CFLAGS)' 를 포함한다.

묵시적 규칙들안에 사용된 변수들은 두가지 클래스들로 구분된다; 프로그램들의 이름인 것들(CC 와 같이)과, 프로그램에 대한 매개변수들을 담고 있는 것들(CFLAGS 와 같이). ("프로그램의 이름" 도 또한 어떤 명령 매개변수들을 가질 수 있지만 이것은 반드시 실제의 실행 프로그램 이름으로 시작해야 한다.) 하나 이상의 변수 값을 가진다면 그것들을 공백문자들로 구분하라.

다음은 내장 규칙들 안에서 프로그램들의 이름으로 사용되는 변수들을 모은 테이블이다:

AR
아카이브-관리 프로그램; 디폴트는 `ar'.
AS
어셈블리 수행 프로그램; 디폴트는 `as'.
CC
C 프로그램을 컴파일하는 프로그램; 디폴트는 `cc'.
CXX
C++ 프로그램들을 컴파일하는 프로그램; 디폴트는 `g++'.
CO
RCS 로부터 파일을 추출하는 프로그램; 디폴트는 `co'.
CPP
결과는 표준 출력으로 내는, C 선행처리기를 실행하는 프로그램; 디폴트는 samp{$(CC) -E}.
FC
포트란과 Ratfor 프로그램들을 컴파일하거나 선행처리하는 프로그램; 디폴트는 `f77'.
GET
SCCS 로부터 파일을 추출하는 프로그램; 디폴트는 `get'.
LEX
Lex 문법들을 C 프로그램들이나 Ratfor 프로그램들로 변환하는 데 사용되는 프로그램; 디폴트는 `lex'.
PC
파스칼 프로그램들을 컴파일하는 프로그램; 디폴트는 `pc'.
YACC
Yacc 문법들을 C 프로그램들로 변환하는 데 사용되는 프로그램; 디폴트는 `yacc'.
YACCR
Yacc 문법들을 Ratfor 프로그램들로 변환하는 데 사용되는 프로그램; 디폴트는 `yacc -r'.
MAKEINFO
Texinfo 소스 파일을 Info 파일로 변환하는 프로그램; 디폴트는 `makeinfo'.
TEX
TeX 소스로부터 TeX DVI 를 만드는 프로그램; 디폴트는 `tex'.
TEXI2DVI
Texinfo 소스로부터 TeX DVI 파일들을 만드는 프로그램; 디폴트는 `texi2dvi'.
WEAVE
Web 을 TeX 로 변환하는 프로그램; 디폴트는 `weave'.
CWEAVE
C Web 을 TeX 로 변환하는 프로그램; 디폴트는 `cweave'.
TANGLE
Web 을 파스칼로 변환하는 프로그램; 디폴트는 `tangle'.
CTANGLE
C Web 을 C 로 변환하는 프로그램; 디폴트는 `ctangle'.
RM
파일을 제거하는 명령; 디폴트 `rm -f'.

다음은 이것의 값들이 위에 있는 프로그램들에 대한 추가의 매개변수들이 되는 변수들을 모은 테이블이다. 이런 모든 것들에 대한 디폴트는 다른 언급이 없다면 빈 문자열이다.

ARFLAGS
아카이브-관리 프로그램에 주어지는 플래그; default `rv'.
ASFLAGS
어셈블러에 주어지는 여분의 플래그 (`.s'`.S' 파일에 대해서 명시적으로 호출되었을 때).
CFLAGS
C 컴파일러에게 주어지는 여분의 플래그.
CXXFLAGS
C++ 컴파일러에게 주어지는 여분의 플래그.
COFLAGS
RCS co 프로그램에게 주어지는 여분의 플래그.
CPPFLAGS
C 선행처리기와 이것을 사용하는 프로그램(C 그리고 포트란 프로그램)에게 주어지는 여분의 플래그.
FFLAGS
포트란 컴파일러에게 주어지는 여분의 플래그.
GFLAGS
SCCS get 프로그램에 주어지는 여분의 플래그.
LDFLAGS
링커 `ld' 를 호출할 것으로 추정되는 컴파일러에게 주어지는 여분의 플래그.
LFLAGS
Lex 에게 주어지는 여분의 플래그.
PFLAGS
파스칼 컴파일러에게 주어지는 여분의 플래그.
RFLAGS
Ratfor 프로그램들에 대해서 포트란 컴파일러에게 주어지는 여분의 플래그.
YFLAGS
Yacc 에게 주어지는 여분에 플래그.

묵시적 규칙의 연쇄(Chains of Implicit Rules)

때때로 어떤 파일은 묵시적 규칙들을 순차적으로 적용해서 만들어질 수 있다. 예를 들어서 `n.o' 라는 파일은 맨먼저 Yacc 를 실행하고 그 다음 cc를 실행해서, `n.y'로부터 만들어질 수 있다. 이런 시퀀스는 연쇄(chain) 라고 불린다.

`n.c' 이 존재한다면, 또는 makefile 에서 언급되었다면, 어떤 특수한 검색도 필요하지 않다; make`n.c' 로부터 C 컴파일을 통해서 오브젝트 파일이 만들어질 수 있다는 것을 안다; 나중에 `n.c' 를 만드는 방법을 생각할 때, Yacc 를 실행하기 위한 규칙이 사용된다. 결국 두 `n.c'`n.o' 이 갱신된다.

그러나 `n.c' 이 존재하지 않고 언급되지도 않았다하더라도, make는 그것이 `n.o'`n.y' 사이에서 끓긴 고리라는 것을 안다. 이런 경우 `n.c'중간 파일(intermediate file) 이라고 불린다. 일단 make가 중간 파일을 사용하기로 결정하였다면 이것은 마치 makefile안에서 언급된 것처럼, 그것을 생성하는 묵시적 규칙과 함께 데이터베이스에 넣어지게 된다.

중간 파일들은 모든 다른 파일들처럼 그들의 규칙을 사용해서 다시 만들어진다. 그러나 중간 파일들은 다음과 같은 두가지 방식으로 다르게 취급된다.

첫번째 다른점은, 중간 파일이 존재하지 않을 때 일어나는 것이다. 일반 팡리 b 가 존재하지 않고 makeb 에 종속적인 타겟을 생각한다면 이것은 항상 b를 생성한 다음 b로부터 그 타겟을 갱신한다. 그러나 b가 중간 파일이라면 make는 그대로 둘 수도 있다. 이것은 b 또는 궁극적인 타겟을, b의 어떤 종속물도 타겟보다 더 새로운 것이 아니거나 그 타겟을 갱신할 어떤 다른 이유가 없다면, 갱신하려고 하지 않는다.

두번째 다른점은, make가 어떤 다른 것을 갱신하기 위해서 b를 생성한다면, 이것이 더이상 필요없을 때 b를 지운다는 것이다. 그러므로 make 이전에 존재하지 않던 중간 파일은 make 이후에도 존재하지 않는다. make는 어떤 파일이 삭제되고 있는가를 보여주는 `rm -f' 명령을 인쇄함으로써 그 삭제 사실을 여러분에게 보고한다.

일반적으로 어떤 파일은 이것이 makefile에서 타겟이나 종속물로 언급된다면 중간 파일이 될 수 없다. 그러나 특수 타겟 .INTERMEDIATE 의 종속물 리스트에 넣어서 어떤 파일을 명시적으로 중간 파일로 지정할 수 있다. 이것은 그 파일이 어떤 다른 식으로 언급되었다 하더라도 효력을 발휘한다.

중간 파일의 자동 삭제를 그 파일을 이차(secondary) 파일로 지정함으로써 막을 수 있다. 이렇게 하기 위해서 이것을 특수 타겟 .SECONDARY 의 종속물 리스트에 넣으면 된다. 어떤 파일이 이차이라면 make는 그 파일이 사전에 존재하지 않는다는 이유 하나만으로 생성하지는 않을 것이다. 그러나 make 는 그 파일을 자동으로 지우지 않는다. 어떤 파일을 이차로 지정하는 것은 그것을 또한 중간 파일로 지정하는 것이다.

묵시적 규칙(`%.o'와 같은) 의 타겟 패턴을 특수 타겟 .PRECIOUS 의 종속물로 지정해서 타겟 패턴이 그 파일의 이름과 일치하는 묵시적 규칙들에 의해서 만들어진 중간 파일들을 보존할 수 있다. section make를 인터럽트 또는 죽이기(Interrupting or Killing make) 참조.

하나의 연쇄가 두개보다 많은 묵시적 규칙들을 가지고 있을 수 있다. 예를 들어서 RCS, Yacc, 그리고 cc 를 실행해서 `RCS/foo.y,v' 로부터 `foo' 를 만드는 것이 가능하다. 여기서 두 파일 `foo.y'`foo.c' 이 마지막에 지워지는 중간 파일드이다.

어떤 묵시적 규칙도 연쇄에서 두번 이상 나타날 수 없다. 이것은 make 가 링커를 두번 실행해서 `foo.o.o' 로부터 `foo'를 만드는 것과 같은 이상한 일을 생각하지 않을 것이라는 것을 의미한다. 이런 제약은 묵시적 규칙 연쇄를 찾으면서 무한 루프에 빠지는 것을 막는 또다른 장점을 가진다.

그렇치 않다면 규칙 연쇄들에 의해서 처리될, 어떤 경우들을 최적화하는 몇가지 특수 묵시적 규칙들이 있다. 예를 들어서 `foo'`foo.c' 로부터 만드는 것은 file{foo.o} 를 중간 파일로 사용해서, 분리된 연쇄 규칙들로 컴파일되고 링크됨으로써 처리될 수 있을 것이다. 그러나 이런 경우 실제로 일어나는 것은 단일 cc 명령으로 컴파일과 링크를 같이 수행하는 특수한 규칙 하나이다. 이런 최적화된 규칙은 규칙들의 순서에서 좀 더 먼저 오기 때문에 스텝-바이-스텝 연쇄보다 더 우선 적용된다.

패턴 규칙을 정의하고 재정하기(Defining and Redefining Pattern Rules)

여러분은 패턴 규칙(pattern rule) 을 작성해서 묵시적 규칙을 정의한다. 패턴 규칙은 일반 규칙과, 이것의 타겟이 `%' (그들중 정확히 한개) 문자를 가지고 있다는 점을 제외하고는, 동일하다. 이 타겟은 파일 이름들과 일치하는 패턴으로 생각된다; `%'는 빈 서브문자열이 아니라면 무엇과도 일치할 수 있는 것이다. 반면에 다른 문자들은 그들 자신들과만 일치한다. 그들이 이름들이 타겟 이름과 관련된 방법을 보여주기 위해서 종속물들은 `%'를 사용한다.

그래서 `%.o : %.c' 라는 패턴 규칙은 파일 `stem.c' 로부터 `stem.o' 라는 파일을 만드는 방법을 말한다.

`%' 을 패턴 규칙들에서 사용한 확장이, makefile이 읽힐 때 발생하는 다른 변수나 함수 확장 후에 발생되는 것에 주의하자. See section 변수 사용 방법(How to Use Variables), 그리고 section 텍스트 변환을 위한 함수(Functions for Transforming Text).

패턴 규칙에 대한 소개(Introduction to Pattern Rules)

패턴 규칙은 타겟 안에 `%' 문자 (정확히 그들 중 하나) 를 담고 있다; 그렇지 않으면 이것은 일반 규칙과 완전히 똑같이 보일 것이다. 타겟은 파일이름들과 일치하는 패턴이다; `%' 는 임의의 빈 것이 아닌 부분문자열과 일치하고 다른 문자들은 그들 자신들과만 일치한다.

예를 들어서, 패턴으로써 `%.c'`.c'로 끝나는 임의의 파일 이름과 일치한다. 패턴으로써 `s.%.c'`s.' 로 시작하고 `.c' 로 끝나며 적어도 다섯개의 문자 이상으로 이루어진 임의의 파일 이름과 일치한다. (`%' 와 일치하는 문자가 적어도 하나 있어야 한다.) `%' 와 일치하는 부분문자열은 줄기(stem) 이라고 불린다.

패턴 규칙의 종속물 안에 있는 `%' 는 타겟에서 `%' 와 일치한 것과 동일한 줄기(stem) 을 나타낸다. 패턴 규칙이 적용되기 위해서 그것의 타겟 패턴은 그 파일 이름과 반드시 일치해야 하며 그것의 종속물 패턴은 반드시 존재하거나 만들어질 수 있는 파일들의 이름을 갖고 있어야 한다. 이런 파일들은 그 타겟의 종속물들이 된다.

그래서 다음과 같은 형태의 규칙은

%.o : %.c ; command...

`n.o' 를, `n.c' 파일이 존재하거나 만들어질 수 있다면 종속물 `n.c' 파일을 가지고 만드는 방법을 지정한다.

`%' 를 사용하지 않는 종속물들이 있을 수 있다; 그런 종속물은 이런 패턴 규칙에 의해서 만들어진 모든 파일들에 첨부된다. 이런 변하지 않는 종속물들은 종종 유용하다.

패턴 규칙은 `%' 를 담고 있는 종속물들을 반드시 가질 필요가 없다. 또는 실제 아무런 종속물을 안가져도 된다. 그런 규칙은 효율적으로 일반 와일드 카드가 된다. 이것은 타겟 패턴과 일치하는 임의의 파일을 만드는 방법을 제공한다. See section 최후의 디폴트 규칙 정의(Defining Last-Resort Default Rules).

패턴 규칙들은 한가지 타겟 이상 가질 수 있다. 일반 규칙들과는 다르게 이런 것은 동일한 종속물들과 명령들을 가진 다른 많은 규칙들과 다르게 작동한다. 어떤 패턴 규칙이 다수의 타겟들을 가진다면, make 는 그 규칙의 명령들이 그 타겟들 모두를 만드는 책임이 있다고 이해한다. 명들들은 타겟들 전부를 만들기 위해서 단 한번만 실행된다. 타겟과 일치하는 패턴 규칙을 검색할 때, 규칙을 필요로 하는 타겟과 일치하는 것(규칙)과 다른 규칙의 타겟 패턴들이 흔히 있다: make 는 현재 문제가 되는 파일에 명령들과 종속물들을 주는 것에 대해서만 신경을 쓴다. 그러나 이 파일의 명령들이 실행중일 때 다른 타겟들은 그들 자신이 갱신된 것처럼 마킹된다.

패턴 규칙들이 makefile 에서 나타나는 순서는 아주 중요하다. 왜냐면 이것이 바로 그들이 생각되어지는 순서이기 때문이다. 동일하게 적용가능한 규칙들 중에서 단지 맨처음 찾아진 것만이 사용된다. 여러분이 작성한 규칙들은 내장된 규칙들보다 더 우선한다. 그러나 종속물들이 실제로 존재하거나 언급된 규칙은 항상, 다른 묵시적 규칙들에 의해서 반드시 만들어져야 하는 종속물들을 가진 규칙보다 우선한다는 것을 주의하자.

패턴 규칙 예제(Pattern Rule Examples)

다음은 make에 의해서 실제로 미리 정의된 패턴 규칙들의 몇가지 예제들이다. 먼저 `.c' 파일들을 `.o' 로 컴파일하는 규칙은:

%.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

이것은 `x.c' 으로부터 `x.o' 파일을 만들수 있는 규칙을 정의한다. 명령은 규칙이 적용될 때마다 타겟 파일 이름들과 소스 파일 이름들을 대입하기 위한 자동 변수들 `$@'`$<' 를 사용하고 있다. (see section 자동 변수들(Automatic Variables)).

다음은 두번째 내장 규칙이다:

% :: RCS/%,v
        $(CO) $(COFLAGS) $<

이것은 서브디렉토리 `RCS' 에서 대응하는 파일 `x,v' 로부터 `x' 파일을 만들 수 있는 규칙을 정의한다. 타겟이 `%' 이기 때문에 이 규칙은, 적절한 종속 파일이 존재한다면, 임의의 파일 무엇에나 용될 것이다. 더블 콜론 은 이 규칙을 terminal 로 만든다. terminal 이란 그것의 종속물이 중간 파일이 아니어야 한다는 것을 의미한다. (see section 임의의 것과도 일치하는 패턴 규칙(Match-Anything Pattern Rules)).

다음 패턴 규칙은 다음과 같은 두 타겟들을 가진다:

%.tab.c %.tab.h: %.y
        bison -d $<

이것은 make 에게 `bison -d x.y' 명령이 `x.tab.c'`x.tab.h' 둘다 make 하라고 말하는 것이다. `foo'`parse.tab.o'`scan.o' 에 종속적이고 `scan.o' 파일이 `parse.tab.h' 에 종속적이면, `parse.y' 파일이 변경될 때, `bison -d parse.y' 이 단 ㅏㄴ번 실행될 것이고 두 파일 `parse.tab.o', `scan.o' 의 종속성들이 만족될 것이다. (아마 `parse.tab.o' 파일이 `parse.tab.c' 로부터 그리고 `scan.o' 파일이 `scan.c' 로부터 재컴파일 될 것이고 `foo' 파일은 `parse.tab.o', `scan.o', 그리고 다른 종속물들로 링크될 것이며 이것은 그리고 나서 해피하게 실행될 것이다.)

자동 변수들(Automatic Variables)

`.c' 파일을 `.o' 파일로 컴파일하는 패턴 규칙을 작성하고 있다고 가정해보자: 그렇다면 어떻게 `cc' 명령이 적절한 소스 파일에 대해서 작동하도록 작성할 것인가? 그 소스 파일 이름을 명령에 쓸 수 없다. 왜냐면 그 이름은 묵시적 규칙이 적용되는 때마다 다를 것이기 때문이다.

해야할 일은 make의 특수 기능, 자동 변수(automatic variables) 를 사용하는 것이다. 이런 변수들은 실행되는 각 규칙에 대해서 매번 새롭게, 규칙의 종속물들과 타겟에 기반해서 다시 계산되는 값을 가진다. 이 예에서 `$@' 를 오브젝트 파일 이름에 대해서 그리고 `$<' 를 소스 파일 이름에 대해서 사용하면 될 것이다.

다음은 자동 변수들을 모아본 테이블이다:

$@
규칙에 있는 타겟의 파일 이름. 타겟이 아카이브 멤버이면 `$@'는 아카이브 파일의 이름이다. 여러개의 타겟들(see section 패턴 규칙에 대한 소개(Introduction to Pattern Rules))을 가지고 있는 패턴 규칙에서 `$@'는 규칙의 명령이 실행되도록 만든 타겟이면 무엇이든 이 타겟의 이름이 된다.
$%
타겟이 아카이브 멤버(See section 아카이브 파일을 갱신하기 위해서 make 사용하기(Using make to Update Archive Files))일 때, 타겟 멤버 이름. 예를 들어서 타겟이 `foo.a(bar.o)'이면 `$%'`bar.o'이고 `$@'`foo.a'이다. 타겟이 아카이브 멤버가 아니면 `$%'는 빈 것이 된다.
$<
첫번째 종속물의 이름. 타겟이 묵시적 규칙으로부터 그의 명령들을 얻었다면 이것은 묵시적 규칙에 의해서 추가된 첫번째 종속물이 될 것이다 (see section 묵시적 규칙(Using Implicit Rules)).
$?
타겟보다 더 새로운 모든 종속물들의 이름들. 이들 사이에는 스페이스들이 들어간다. 아카이브 멤버들인 종속물들에 대해서 이름이 있는 멤버만이 사용된다 (see section 아카이브 파일을 갱신하기 위해서 make 사용하기(Using make to Update Archive Files)).
$^
모든 종속물들의 이름. 이들 사이에는 스페이스들이 들어간다. 아카이브 멤버인 종속물들에 대해서 이름있는(지정된?) 멤버만이 사용된다 (see section 아카이브 파일을 갱신하기 위해서 make 사용하기(Using make to Update Archive Files)). 타겟은 이것이 의존하는 다른 각 파일들에 대해서 각 파일이 종속물 리스트에서 몇번이나 나왔는가에 상관없이, 딱 한번만 사용한다. 그래서 어떤 타겟을 위해서 한번 이상 종속물을 사용한다면 $^ 의 값은 그 이름을 딱 한번 담고 있는 형태가 된다.
$+
이것은 `$^' 와 비슷하다. 그러나 종속물들이 makefile 에서 리스트된 순서와 나타난 대로 중복되었다고 해도 한번 이상 리스트된다. 이것은 특별한 순서로 라이브러리 파일 이름들을 반복하는 것이 의미가 있는 링크 명령들 안에서 주로 유용하다.
$*
묵시적 규칙이 일치하는 (see section 패턴 비교 방법(How Patterns Match)) 대상 줄기(stem). 타겟이 `dir/a.foo.b' 이고 타겟 패턴이 `a.%.b' 이라면 줄기는 `dir/foo' 이다. 줄기는 관련된 파일들의 이름을 만들때 유용하다. 정적 패턴 규칙에서 줄기는 타겟 패턴에서 `%' 과 일치한, 파일 이름의 일부분을 말한다. 명시적 규칙에서는 줄기가 없다; 그래서 `$*' 는 그런식으로 결정될 수 없다. 대신에 타겟 이름이 인식된 접미사로 끝난다면 (see section 구닥다리 접미사 규칙(Old-Fashioned Suffix Rules)), `$*' 는 타겟 이름 빼기 접미사로 설정된다. 예를 들어서, 타겟 이름이 `foo.c' 이라면, `$*'`foo' 로 설정된다, 왜냐면 `.c' 가 접미사이기 때문이다. GNU make 는 다른 make 구현물과의 호환성을 위해서만 이런 괴기스런 일을 한다. 일반적으로 묵시적 규칙들이나 정적 패턴 규칙들을 제외하고는 `$*' 를 쓰지 않도록 해야 할 것이다. 명시적 규칙 안의 타겟 이름이 인식된 접미사로 끝나지 않는다면 `$*' 는 그 규칙에 대해서 빈 문자열로 설정된다.

`$?' 는 변경한 종속물들에 대해서만 작업을 하고자 할 때, 명시적 규칙들 안에서도 유용하다. 예를 들어서 `lib' 라는 이름의 아카이브가 몇개의 오브젝트 파일들의 복사물들을 담고 있다고 가정해보자. 다음 규칙은 변경된 오브젝트 파일들만을 아카이브에다 넣을 것이다:

lib: foo.o bar.o lose.o win.o
        ar r lib $?

위에서 리스트된 변수들(자동 변수들)중에서, 네개는 단일 파일 이름들인 값들을 가지고 두개는 파일 이름들의 리스트들인 값들을 가진다. 이런 여섯개 변수들은 파일의 디렉토리 이름이나 디렉토리 내의 파일 이름과 같은 값을 추출하는 변종들을 가진다. 변종 변수들의 이름들은 각각 `D'`F' 를 붙여서 이루어진다. 이런 변종들은 GNU make 에서 반쯤 구닥다리이다. 왜냐면 dirnotdir 함수들이 동일한 효과를 얻는데 사용될 수 있기 때문이다 (see section 파일 이름들을 위한 함수(Functions for File Names)). 그러나 `F' 변종들은 dir 함수의 결과에서는 항상 나타나는 마지막 슬래쉬를 모두 제거한다는 사실에 주목하자. 다음은 변종들의 테이블이다:

`$(@D)'
The directory part of the file name of the target, with the trailing slash removed. If the value of `$@' is `dir/foo.o' then `$(@D)' is `dir'. This value is `.' if `$@' does not contain a slash.
`$(@F)'
타겟의 파일 이름에서 디렉토리 파트에 들어 있는 파일 부분을 가리킨다. `$@' 의 값이 `dir/foo.o' 이라면 `$(@F)'`foo.o' 이다. `$(@F)'`$(notdir $@)' 과 동일하다.
`$(*D)'
`$(*F)'
줄기의 디렉토리 부분과 디렉토리 파트 안에 들어 있는 파일 부분을 가리킨다; 이 예제의 경우라면 `dir'`foo' 가 될 것이다.
`$(%D)'
`$(%F)'
타겟 아카이브 멤버 이름 중에서 디렉토리 파트와 디렉토리 파트 안에 들어 있는 파일 부분을 가리킨다. 이것은 `archive(member)' 형태의 아카이브 멤버 타겟들에 대해서만 의미가 있고 member 가 디렉토리 이름을 갖고 있을 때만 유용하다. (See section 타겟으로써 아카이브 멤버(Archive Members as Targets0.)
`$(<D)'
`$(<F)'
첫번째 종속물의 디렉토리 파트와 디렉토리 파트 안에 들어 있는 파일 부분을 가리킨다.
`$(^D)'
`$(^F)'
모든 종속물들의 디렉토리 부분들과 디렉토리에 들어 있는 파일 부분들을 가리킨다.
`$(?D)'
`$(?F)'
타겟보다 더 새로운 모든 종속물들의 디렉토리 부분들과 디렉토리 내 파일들 부분을 가리킨다.

이런 자동 변수들에 대해서 얘기할 때 특별한 스타일의 관례를 사용한다는 것에 주목하자; objectsCFLAGS 와 같은 일반 변수들에 대해서 작성할 때 "변수 <" 가 아니라 "`$<'의 값" 라고 쓴다. 이런 관례가 이런 특별한 경우에 좀 더 자연스럽게 보인다고 생각한다. 이것이 아주 깊은 중요성을 가진다고 추측하지 말자; `$<'`$(CFLAGS)'CFLAGS라는 이름의 변수를 참조하는 것처럼, < 라는 변수를 참조하는 것이다. `$<' 자리에 `$(<)' 라는 변수를 쓸수도 있다.

패턴 비교 방법(How Patterns Match)

타겟 패턴은 둘 중에 또는 둘다 빈 것일 수 있는, 접두사와 접미사 사이에 하나의 `%' 를 가진 것이다. 어떤 파일 이름이 중복없이, 접두사로 시작하고 접미어로 끝나면 패턴이 일치하는 것이다. 접두사와 접미사 사이의 텍스트는 줄기(stem) 이라고 불린다. 그래서 패턴 `%.o'`test.o' 와 일치하면 줄기는 `test' 인 것이다. 패턴 규칙 종속물들은 `%' 문자에 줄기들을 대입해서 만들어진 실제 파일 이름들이다. 그래서 동일한 예제에서 종속물들 중의 하나가 `%.c' 로 작성되면 이것은 `test.c' 로 확장된다.

타겟 패턴이 슬래쉬를 갖지 않으면(그리고 보통 이것은 그렇지 않다), 파일 이름에서 디렉토리 이름들은 그 파일 이름에서, 타겟 접두사와 접미사와 비교되기전에, 제거된다. 파일 이름을 타겟 패턴과 비교한 후 디렉토리 이름들은, 이들 마지막에 있는 슬래쉬와 함께, 패턴 규칙의 종속물 패턴들과 그 파일 이름으로부터 만들어지는 종속물 파일에 더해진다. 디렉토리들은 사용할 묵시적 규칙을 찾을 목적으로만 무시된다. 그러나 그 규칙의 적용에서는 무시되지 않는다. 그래서 `e%t'`src/eat' 과 일치하는 것이고 여기서 `src/a' 이 줄기이다. 종속물들이 파일 이름들이 되면 줄기로부터 디렉토리들이 그 앞에 덧붙여진다. 이때 줄기의 나머지가 `%' 에 대입된다. 종속물 패턴 `c%r' 를 가지고 줄기 `src/a' 는 파일 이름 `src/car' 를 제공한다.

임의의 것과도 일치하는 패턴 규칙(Match-Anything Pattern Rules)

패턴 규칙의 타겟이 단지 `%' 이라면 이것은 파일 이름이 무엇이든 이것과 일치하는 것이다. 우리는 이런 규칙을 임의의 것과도 일치하는(match-anything) 규칙이라고 부른다. 이들은 아주 유용하지만 make 가 그들을 생각하는 시간이 많이 든다. 왜냐면 이것은 타겟으로나 종속물로써 리스트된 각 파일 이름들에 대해서 모든 그런 규칙을 생각해야 하기 때문이다.

makefile 이 `foo.c' 를 언급했다고 하자. 이 타겟에 대해서 make 는 오브젝트 파일 `foo.c.o' 를 링크함으로써, 또는 `foo.c.c' 로부터 한번에 C 컴파일하고-링크함으로써, 또는 `foo.c.p' 로부터 파스칼 컴파일하고-링크함으로써, 그리고 기타 등등 많은 다른 가능성들을에 의해서 `foo.c' 를 만들려고 생각해야만 할 것이다.

이런 가능성들이, `foo.c' 이 C 소스 파일이고 실행 파일이 아니기 때문에, 다소 괴상망칙하다는 것을 우리는 안다. make 가 이런 가능성들을 생각하지 않는다면, `foo.c.o'`foo.c.p' 과 같은 파일들이 존재하지 않을것이기 때문에 그런 가능성들을 궁극적으로 거부할 것이다. 그러나 이런 가능성들은 너무 많기 때문에 그것들을 생각해야 한다면 make 는 아주 느리게 작동할 것이다.

속도를 더 높이기 위해서 make 가 임의의것과도 일치하는 규칙들을 생각할 때 다양한 제약을 둔다. 적용될 수 있는 제약은 두개 있다. 임의의것과도 일치하는 규칙을 정의할 때마다, 그런 규칙에 대해서 하나 또는 다른 하나를 반드시 선택해야만 한다.

한가지 선택은 임의의것과도 일치하는 규칙을 더블 콜론으로 정의함으로써 terminal 로 마킹하는 것이다. 규칙이 terminal 이면 이것은, 그것의 종속물들이 실제로 존재하지 않는 한 적용되지 않는다. 다른 묵시적 규칙들로 만들어질 수 있는 종속물들은 좋은 것이 아니다. 다른 말로 하면 terminal 규칙을 넘어서 더이상의 연쇄 작용이 일어나지 않는다.

예를 들어서 RCS 와 SCCS 파일들로부터 소스들을 추출하는 내장된 묵시적 규칙들은 terminal 이다; 결과적으로 파일 `foo.c,v' 이 존재하지 않는다면 make`foo.c,v.o'`RCS/SCCS/s.foo.c,v' 로부터 중간 파일로써 그것을 마들려고 생각조차 하지 않을 것이다. RCS 와 SCCS 파일들은 일반적으로 최종 소스 파일들이다. 이들은 다른 파일들로부터 다시 만들어지면 안된다; 그러므로 make는 그것들을 다시 만드는 방법들을 찾지 않음으로써 시간을 절약할 수 있다.

임의의것과 일치하는 규칙을 terminal 로 마킹하지 않으면, 이것은 비-terminal. 비-terminal 임의의것과 일치하는 규칙은 특정한 데이터 타입을 가리키는 파일 이름에 적용될 수 없다. 어떤 파일 이름은, 비-임의의것과 일치하는 묵시적 규칙 타겟이 그것과 일치할 경우, 특정 데이터 타입을 가리킨다.

예를 들어서 `foo.c' 는 패턴 규칙 `%.c : %.y' (Yacc 를 실행하는 규칙) 에 대한 타겟과 일치한다. 이 규칙이 실제로 적용가능한가 아닌가에 (파일 `foo.y' 이 존재할때만 발생한다) 대해서 생각할 필요 없이, 그것이 타겟이 일치한다는 사실로써 파일 `foo.c' 에 대한 비-terminal 임의의것과도 일치하는 규칙들 중의 아무거나를 생각하는 것을 막기에는 충분하다. 그래서 make`foo.c'`foo.c.o', `foo.c.c', `foo.c.p', 등으로부터 실행 파일로써 만들어볼려는 시도를 생각조차 않는다.

비-terminal 임의의것과 일치하는 규칙들이 특정한 데이터 타입들(실행 파일과 같은)을 담고 있는 파일들과을 만드는 데 사용된다는 것과, 인식된 접미사를 가지는 파일 이름들이 어떤 다른 특정한 데이터 타입(C 소스 파일과 같은)을 가리킨다는 것이 이런 제약의 동기이다.

특수한 내장된 더미 패턴 규칙들은 특정 파일 이름들을 인식해서 비-terminal 임의의것과 일치하는 규칙들이 생각되지 않도록 하기 위해서만 제공된다. 이런 더미 규칙들은 종속물들과 명령들을 가지지 않고 모든 다른 목적들에 대해서 무시된다. 예를 들어서 다음과 같은 내장된 묵시적 규칙은

%.p :

`foo.p' 과 같은 파스칼 소스 파일들이 특정한 타겟 패턴과 일치하므로 `foo.p.o'`foo.p.c' 를 찾느라고 시간을 허비하지 못하도록 하기 위해서 존재한다.

`%.p' 를 위한 것과 같은 더미 패턴 규칙들은 접미사 규칙들에서의 사용을 위해서 유효하게 나열된 모든 접미사들에 대해서 만들어진다 (see section 구닥다리 접미사 규칙(Old-Fashioned Suffix Rules)).

묵시적 규칙 취소시키기(Canceling Implicit Rules)

내장 묵시적 규칙(또는 사용자가 정의한 것)을 동일한 타겟과 종속물들을 가지지만 명령들이 다른 새로운 패턴 규칙을 정의함으로써 오버라이드할 수 있다. 새로운 규칙이 정의될 때 내장 규칙이 대체된다. 새로운 규칙이 차지하는 묵시적 규칙들 시퀀스에서의 위치는 그 새로운 규칙을 작성한 위치에 의해서 결정된다.

내장 묵시적 규칙과 동일한 타겟과 종속물들을 가지지만 명령들은 없는 패턴 규칙을 정의함으로써 저 내장 묵시적 규칙을 취소할 수 있다. 예를 들어서 다음은 어셈블러를 실행하는 규칙을 취소할 것이다:

%.o : %.s

최후의 디폴트 규칙 정의(Defining Last-Resort Default Rules)

종속물들을 하나도 갖지 않는 제일-마지막(terminal) 임의의것과도 일치하는 패턴 규칙을 작성함으로써, 마지막(last-resort) 묵시적 규칙을 정의할 수 있다 (see section 임의의 것과도 일치하는 패턴 규칙(Match-Anything Pattern Rules)). 이것은 다른 패턴 규칙과 비슷하다; 이것은 임의의 타겟과도 일치할 것이다는 것이 이것이 특별한 유일한 것이다. 그래서 그런 규칙의 명령들은, 자신의 명령들을 가지지 않는 모든 타겟들과 종속물들에 대해서 그리고 다른 묵시적 규칙이 적용되지 않는 것들에 대해서 사용된다.

예를 들어서 makefile 을 테스트할 때 소스 파일들이 실제 데이터를 가지고 있는 것인가 신경쓰지 않고, 대신 그들이 존재하는가 안하는가만 신경쓸 수도 있다. 그렇다면 다음과 같이 할 수도 있다:

%::
        touch $@

이것은 (종속물로써) 필요한 모든 소스 파일들이 자동으로 생성되도록 한다.

이것 대신 전혀 규칙들이 없는, 심지어 명령들을 지정하지 않는 규칙의, 타겟들에 대해서 사용되는 명령들을 정의할 수 있다. 이렇게 하기 위해서 .DEFAULT 타겟에 대한 규칙을 작성하면 된다. 그런 규칙의 명령들은 명시된 규칙의 타겟들로 나타나지 않는, 어떤 묵시적 규칙도 적용되지 않는, 종속물들에 대해서 사용된다. 일반적으로 작성하지 않으면 .DEFAULT 은 없다.

다음과 같이 .DEFAULT 를 명령이나 종속물들이 없이 사용한다면:

.DEFAULT:

.DEFAULT 에 대해서 이전에 정의된 명령들이 삭제된다. 그러면 make.DEFAULT 를 전혀 정의하지 않은 것처럼 작동할 것이다.

어떤 타겟이 임의의것과도 일치하는 패턴이나 .DEFAULT 으로부터 명령들을 얻기를 원하지 않지만, 또한 어떤 명령도 그런 타겟에 대해서 실행되는 것을 원하지 않는다면, 이것에게 빈 명령들을 줄 수 있다 (see section 빈 명령 사용하기(Using Empty Commands)).

마지미가 규칙을 사용해서 다른 makefile 의 일부를 오버라이드할 수 있다. See section 다른 Makefile의 일부를 오버라이딩(Overriding Part of Another Makefile).

구닥다리 접미사 규칙(Old-Fashioned Suffix Rules)

접미사 규칙(Suffix rules) 이란 make 에 대해서 묵시적 규칙들을 정의하는 오래된-스타일의 방법이다. 접미사 규칙들은 패턴 규칙들이 좀 더 일반적이고 좀 더 명료하기 때문에 사장되었다. 오래된 makefile 들과의 호환성을 위해서 GNU make 는 이것을 지원한다. 그들은 다음 두가지 종류가 있다: 더블-접미사(double-suffix)단일-접미사(single-suffix).

더블-접미사 규칙은 두개의 접미사들로 정의된다: 타겟 접미사와 소스 접미사. 이것은 파일의 이름이 타겟 접미사로 끝나는 어떤 파일과도 일치한다. 대응하는 묵시적 종속물은 타겟 접미사를 소스 접미사로 바꿔서 만들어진다. 타겟과 소스 접미사들이 `.o'`.c' 인 두-접미사 규칙 은 패턴 규칙 `%.o : %.c' 와 동일하다.

단일-접미사 규칙은 단일 접미사로 정의된다. 이것은 소스 접미사이다. 단일-접미사 규칙은 임의의 파일들과 일치하고 대응하는 묵시적 종속물 이름은 소스 접미사를 덧붙여서 만들어진다. 소스 접미삭 `.c' 인 단일-접시사 규칙은 패턴 규칙 `% : %.c' 와 동일하다.

접미사 규칙 정의들은 각 규칙의 타겟과, 정의된 (알려진) 접미사 리스트와 비교해서 인식된다. make 가 타겟이 알려진 접미사인 규칙을 보면 이 규칙은 단일-접미사 규칙으로 생각된다. make 가 타겟이 두개의 알려진 접미사들이 서로 붙은 형태인 규칙을 보면 이 규칙은 더블-접미사 규칙으로 취급된다.

예를 들어서 `.c'`.o' 는 알려진 접미사 디폴트 리스트에 둘 다 있는 것이다. 그러므로 타겟이 `.c.o' 인 규칙을 정의하면 make 는 이것을 소스 접미사는 `.c' 이고 타겟 접미사는 `.o' 인 더블-접미사로 생각한다. 다음은 C 소스 파일을 컴파일하기 위한 규칙을 정의하는 오래된-스타일의 방법이다:

.c.o:
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

접미사 규칙들은 그들 자신의 종속물을 전혀 가질수 없다. 그들이 있다면 그들은 접미사 규칙들로 생각되어지는 것이 아니라 이상 이름들을 가진 일반 파일들로 생각된다. 그래서 다음 규칙은:

.c.o: foo.h
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

`.c.o' 를 종속 파일 `foo.h' 로부터 만드는 방법을 말하는 것이 되버리고, 전혀 다음과 같은 패턴 규칙이 아니게 되버린다:

%.o: %.c foo.h
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

이것은 `.c' 파일들로부터 `.o' 파일들을 만드는 방법과 `foo.h' 에 의존하는 이 패턴 규칙을 사용해서 모든 `.o' 파일들을 만드는 방법을 말하는 것이다.

어떤 명령도 없는 접미사 규칙들도 또한 의미가 없다. 그들은 명령들을 가지지 않는 패턴 규칙들이 그러는 것처럼, 이전 규칙들을 지우지 않는다 (see section 묵시적 규칙 취소시키기(Canceling Implicit Rules)). 그들은 데이터베이스에 타겟으로 단순히 접미사나 합쳐친 한쌍의 접미사들을 넣는다.

알려진 접미사들은 단순하게 특수한 타겟 .SUFFIXES 의 종속물들의 이름이다. 사용자 자신의 접미사들을, 다음과 같이 더 많은 종속물들을 더하는 .SUFFIXES 규칙을 작성함으로써, 추가할 수 있다:

.SUFFIXES: .hack .win

이것은 `.hack'`.win' 을 접미사 리스트 마지막에 더한다.

그것들에다 더하는 것 대신에 알려진 디폴트 접미사들을 제거하고자 한다면 종속물들이 전혀 없는 .SUFFIXES 를 작성하면 된다. 특수한 섭리에 의해서 이것은 .SUFFIXES의 모든 존재하는 종속물들을 제거한다. 그리고 난후 사용자가 원하는 접미사들을 더하기 위해서 다른 규칙을 작성할 수 있다. 예를 들어서,

.SUFFIXES:            # Delete the default suffixes
.SUFFIXES: .c .o .h   # Define our suffix list

`-r' 또는 `--no-builtin-rules' 플래그는 디폴트 접미사 리스트를 빈 것으로 만든다.

변수 SUFFIXESmake 가 임의의 makefile 들을 읽기 전에, 접미사 디폴트 리스트들이 정의된다. 특수 타겟 .SUFFIXES 에 대한 규칙으로 접미사들 리스트를 변경할 수 있지만 그것은 이 변수는 바꿀 수 없다.

묵시적 규칙 검색 알고리즘(Implicit Rule Search Algorithm)

다음은 make 가 어떤 타겟 t 에 대해서 묵시적 규칙을 검색하는데 사용하는 과정이다. 이 과정은 명령들이 없는 각 더블-콜론 규칙에 대해서, 명령이 없는 일반 규칙들의 각 타겟에 대해서, 그리고 어떤 규칙에도 타겟이 아닌 각 종속물에 대해서, 수행된다. 이것은 또한, 규칙들의 연쇄를 찾으면서 묵시적 규칙들로부터 오는 종속물들에 대해서, 재귀적으로 수행된다.

접미사 규칙들은 이 알고리즘에서 언급되지 않는다. 왜냐면 접미사 규칙들은 makefile 이 일단 읽히면 동일한 패턴 규칙들로 변환되기 때문이다.

`archive(member)' 형태의 아카이브 멤버 타겟에 대해서 다음 알고리즘이 두번 실행된다. 첫번째는 전체 타겟 이름 t 를 사용하고 두번째는 첫번째가 어떤 규칙도 찾지 못한다면 t 타겟으로써 `(member)' 를 사용한다.

  1. t 를 디렉토리 부분(d 라고 부르자)과 그리고 나머지(n 이라고 부르자)로 분할한다. 예를 들어서 t`src/foo.o' 이라면 d`src/' 이고 n`foo.o' 이다.
  2. 모든 패턴 규칙들 리스트가, 타겟이 tn 과 일치하는 규칙이 되도록 만든다. 타겟 패턴이 슬래쉬를 가지면 이것은 t 와 비교된다; 그렇지 않으면 n 과 비교된다.
  3. 이 리스트에 있는 임의의 규칙이 임의의것과도 일치하는 규칙이 아니라면 모든 비-terminal 임의의것과도 일치하는 규칙들을 이 리스트에서 제거한다.
  4. 리스트에서 명령들이 없는 모든 규칙들을 제거한다.
  5. 리스트에 있는 각 패턴 규칙에 대해서:
    1. 줄기 s 를 찾는다. 이것은 타겟 패턴에서 `%' 와 일치하는 tn 의 빈 것이 아닌 부분이다.
    2. s`%' 에 대해서 대입함으로써 종속물들 이름을 계산한다; 타겟 패턴이 슬래쉬를 가지지 않는다면 d 를 각 종속물 이름 앞에다 덧붙인다.
    3. 모든 종속물들이 존재하거나 존재해야 하는지 검사한다. (어떤 파일 이름이 makefile 에서 타겟으로써 또는 명시적인 종속물로써 언급되었다면 우리는 그것이 반드시 존재해야 하는 것으로 말한다.) 모든 종속물들이 존재하거나 존재해야 한다면, 또는 종속물들이 전혀 없다면, 이 규칙이 적용된다.
  6. 어떤 패턴 규칙도 지금까지 찾지 못했다면 더 어렵게 시도한다. 이 리스트에 있는 각 패턴 규칙에 대해서:
    1. 규칙이 terminal 이라면 이것을 무시하고 다음 규칙으로 간다.
    2. 이전과 같이 종속물들 이름을 계산한다.
    3. 모든 종속물들이 존재하거나 존재해야 하는지 검사한다.
    4. 존재하지 않는 각 종속물에 대해서 다음 알고리즘을 재귀적으로 실행해서, 종속물이 묵시적 규칙에 의해서 찾아질 수 있는가 없는가를 본다.
    5. 모든 종속물들이 존재하거나, 존재해야 하거나, 묵시적 규칙들에 의해서 만들어질 수 있다면, 이 규칙이 적용된다.
  7. 어떤 묵시적 규칙도 적용되지 않는다면 .DEFAULT 에 대한 규칙이, 존재한다면, 적용된다. 이런 경우 t 에게 .DEFAULT 가 가지는 동일한 명령들을 준다. 그렇지 않다면 t 에 대한 명령들은 없는 것이 된다.

일단 적용할 규칙이 찾아지면, t 또는 n 과 일치하는 것과 다른 그 규칙의 각 타겟 패턴에 대해서, 그 패턴에 있는 `%'s 로 교체되고 결과 파일 이름은, 타겟 파일 t를 다시 만들기 위해서 명령들이 실행될 때까지, 저장된다. 이런 명령들이 실행된 후 이들 저장된 파일들 각각은 데이터베이스로 들어가고 갱신된 것으로 그리고 그 파일 t과 같은 갱신 상태를 가지는 것으로 마킹된다.

패턴 규칙의 명령들이 t 에 대해서 실행될 때 자동변수들이 타겟과 종속물들에 대응하여 서정된다. See section 자동 변수들(Automatic Variables).


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