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


makefile 관례(Makefile Conventions)

이 장은 GNU 프로그램들에 대한 makefile을 작성하는 관례를 설명한다.

makefile에 대한 일반 관례(General Conventions for Makefiles)

모든 makefile 은 다음과 같은 라인을 가져야 한다:

SHELL = /bin/sh

SHELL 변수가 환경으로부터 승게될수도 있는 시스템들에서 문제들을 피하기 위해서. (이것은 GNU make 의 문제가 절대로 아니다.)

다른 make 프로그램들은 비호환 접미사 리스트들과 묵시적 규칙들을 가지고 이것은 때때로 혼란과 잘못된 행동을 일으킨다. 그래서 특정한 makefile에서 필요로하는 접미사들로만 이루어진 접미사 리스트를 다음과 같이 설정하는 것은 좋은 생각이다:

.SUFFIXES:
.SUFFIXES: .c .o

첫번째 라인은 접미사 리스트를 청소한다. 두번째 라인은 이 makefile 에서 묵시적 규칙들에 종속적인 모든 접미사들을 도입한 것이다.

`.' 가 명령 실행을 위한 경로에 있을 것이라고 가정하지 말자. make 동안에 사용자의 팩키지 중에서 어떤 프로그램을 실행하고자 할 때, 그 프로그램이 make 의 일부이라면 이것이 `./' 를, 또는 그 파일이 소스 코드의 변경되지 않은 부분일 경우라면 `$(srcdir)/' 를 사용하는 것을 확인하기 바란다. 이런 접두어들 중의 하나가 없다면 현재 검색 경로가 사용된다.

`./' (빌드 디렉토리(build directory)) 와 `$(srcdir)/' (소스 디렉토리(source directory)) 사이의 차이는 사용자들이 `configure' 에 대해서 `--srcdir' 옵션을 사용하여 분리된 디렉토리 안에서 빌드할 수 있기 때문에 중요하다. 다음과 같은 형태의 규칙은:

foo.1 : foo.man sedscript
        sed -e sedscript foo.man > foo.1

빌드 디렉토리가 소스 디렉토리가 아닐 때 실패할 것이다. 왜냐면 `foo.man'`sedscript' 는 소스 디렉토리에 있기 때문이다.

GNU make 를 사용할 때 `VPATH' 에 의존해서 소스 파일을 찾는 것은 단일 종속 파일이 있는 경우에 작동할 것이다. 왜냐면 make 자동 변수 `$<' 는 소스 파일이 어디에 있던간에 그 소스 파일을 표현할 것이기 때문이다. (make 의 많은 버전들이 `$<' 를 묵시적 규칙들 안에서만 설정한다.) 다음과 같은 makefile 타겟은

foo.o : bar.c
        $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o

이것 대신에 다음과 같이 작성되어야 할 것이다.

foo.o : bar.c
        $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@

`VPATH' 가 제대로 작동하도록 하기 위해서 말이다. 타겟이 다수의 종속물들을 가진다면, 명시적인 `$(srcdir)' 를 사용하는 것이 규칙이 제대로 작동하도록 하는 가장 쉬운 방법이다. 예를 들어서 위에서 `foo.1' 를 위한 타겟은 다음과 같이 쓰는 것이 가장 좋은 것이다:

foo.1 : foo.man sedscript
        sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@

GNU 배포판들은 보통 소스 파일들이 아닌 몇가지 파일들을 가지고 있다---예를 들어서, Info 파일, 그리고 Autoconf, Automake, Bison 또는 Flex 로부터 발생된 결과. 이런 파일들이 일반적으로 소스 디렉토리에 나타나기 때문에 그들은 항상 빌드 디렉토리가 아니라 소스 디렉토리에 있어야 한다. 그래서 이들을 갱신하는 Makefile 규칙들은 갱신 파일들을 소스 디렉토리에 넣어야 한다.

그러나 어떤 파일이 배포판에 없다면 Makefile 은 그것을 소스 디렉토리에 넣으면 안된다. 왜냐면 어떤 프로그램을 보통의 환경에서 빌드하는 것은 소스 디렉토리를 어떤 식으로든 변경해서는 안되기 때문이다.

타겟을 빌드하고 설치하는 것이, 적어도(그리고 모든 그들의 서브타겟들이) 병렬 make로도 정확하게 작동하게 만들려고 노력하자.

makefile 의 유틸리티(Utilities in Makefiles)

makefile 명령들(그리고 configure 와 같은 쉘 스크립트들)을 작성할 때 csh 가 아니라 sh 에서 실행하도록 작성하자. kshbash 의 특수 기능들을 사용하지 말자.

configure 스크립트와 makefile 의 빌드와 설치를 위한 규칙들은 다음과 같은 것들을 제외하고는 유틸리티들을 직접 사용해서는 안된다:

cat cmp cp diff echo egrep expr false grep install-info
ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true

압축 프로그램 gzipdist 규칙에서 사용될 수 있다.

이런 프로그램들에 대해서 일반적으로 지원되는 옵션들을 사용하자. 예를 들어서 대부분의 시스템들이 `mkdir -p' 를 지원하지 않기 때문에 이것이 편하더라도 이것을 사용하지 말자.

makefile 안에서 심볼릭 링크를 생성하지 않도록 하는 것은 좋은 생각이다. 왜냐면 소수의 시스템들이 심볼릭 링크를 지원하기 때문이다.

빌드와 설치를 위한 Makefile 규칙들은 컴파일러들과 관련된 프로그램들을 사용할 수 있지만 make 변수들을 통해서 그렇게 해서 사용자가 대안들을 대입할 수 있도록 해야 한다. 다음은 우리가 의미한 프로그램들 몇가지들이다:

ar bison cc flex install ld ldconfig lex
make makeinfo ranlib texi2dvi yacc

다음 make 변수들을 사용해서 이들 프로그램들을 사용하자:

$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX)
$(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)

ranlibldconfig 를 사용할 때 시스템이 문제의 프로그램을 가지고 있지 않다 하더라도 나쁜 일이 일어나지 않도록 해야 한다. 그 명령으로부터 나온 에러를 무시하도록 정렬하고 그 명령이 유저에게 무언가를 말하기 전에, 이 명령이 실제 문제가 아니라고 말하는 메시지를 출력해야 한다. (Autoconf `AC_PROG_RANLIB' 매크로가 이것을 도울 수 있다.)

심볼릭 링크들을 사용한다면 심볼릭 링크들을 가지지 않는 시스템들에 대한 대체물을 구비하여야 한다.

다음과 같은 추가의 유틸리티들이 Make 변수들을 통해서 사용될 수 있다:

chgrp chmod chown mknod

이런 유틸리티들이 존재한다고 알고 있는 특별한 시스템들에 대해서만 의도된 Makefile 일부(또는 스크립트) 안에서 그런 유틸리티들을 사용하는 것은 좋다.

명령을 지정하기 위한 변수(Variables for Specifying Commands)

makefile 은 어떤 명령들, 옵션들, 기타 등등을 오버라이드하기 위한 변수들을 제공해야 한다.

특별히 대부분의 유틸리티 프로그램들을 변수들을 통해서 실행해야 할 것이다. 그래서 Bison 을 사용한다면, 디폴트 값이 `BISON = bison' 로 설정된 BISON 이라는 이름의 변수를 가지고 있다면, Bison 을 사용하고자 할 때마다 그것을 $(BISON) 로 참조하자.

ln, rm, mv, 그리고 기타 등등과 같은 파일 관리 유틸리티들은 이런 식으로 변수들을 통해서 참조될 필요가 없다. 왜냐면 사용들이 그것들을 다른 프로그램들로 변경할 필요가 없기 때문이다.

각 프로그램-이름 변수는 그 프로그램에게 옵션들을 제공하는 데 사용되는 옵션 변수를 함께 가지고 있어야 한다. 프로그램-이름 변수 이름에다 옵션들 변수 이름을 얻기 위해서 `FLAGS' 를 덧붙인다---예를 들어서, BISONFLAGS. (C 컴파일러의 경우 CFLAGS, yacc 의 경우 YFLAGS, lex 의 경우 LFLAGS 이들은 이 규칙의 예외들이지만 그들이 표준이기 때문에 우리는 이들을 사용한다.) 선행처리기를 실행하는 임의의 컴파일 명령에 대해서는 CPPFLAGS 를 사용하고 ld 를 직접 쓰는 경우와 같이 링크를 하는 임의의 컴파일 명령에 대해서는 LDFLAGS 를 쓴다.

특정 파일들을 적절하게 컴파일하는 데 반드시 사용되는 C 컴파일러 옵션들이 있다면 그것들을 CFLAGS 에 넣지 말자. 사용자들은 CFLAGS 를 자유롭게 지정할 수 있을 것이라고 기대한다. 대신에 CFLAGS 와는 독립적으로 C 컴파일러에게 필요한 옵션들을 전달하도록 하자. 그들을 다음과 같이 컴파일 명령들 안에 명시적으로 써넣거나 아니면 묵시적 규칙을 하나 정의해서 말이다:

CFLAGS = -g
ALL_CFLAGS = -I. $(CFLAGS)
.c.o:
        $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<

`-g' 옵션을 CFLAGS 안에 넣자. 왜냐면 그것이 적절한 컴파일에 대해서는 필요하지 않기 때문이다. 이것을 단지 권장일뿐인 디폴트로 생각할 수도 있다. 디폴트 값들로 GCC 를 이용해서 컴파일된 팩키지가 셋업될 것이라면 CFLAGS 의 디폴트 값에다 `-O' 도 함께 포함할 수도 있다.

CFLAGS 를 컴파일러 옵션들을 담고 있는 다른 변수들 뒤에, 사용자가 CFLAGS 를 사용해서 다른 것들을 오버라이드할 수 있도록, 컴파일 명령의 맨마지막에 넣자

CFLAGS 는 C 컴파일러의 모든 호출에서 사용되어야 한다. 컴파일하는 것과 링크를 하는 것 모두에서.

모든 Makefile 은 어떤 파일을 시스템으로 설치하는 기본 명령인 INSTALL 변수를 정의해야 한다.

모든 Makefile 은 INSTALL_PROGRAMINSTALL_DATA 변수들을 또한 정의해야 한다. (이들 각각에 대한 디폴트는 $(INSTALL) 이어야 한다.) 그리고 이런 변수들을 실행 파일들과 비실행 파일들 각각을 위한 실제 설치를 위한 명령들로 사용해야 한다. 이런 변수들을 다음과 같이 사용하자:

$(INSTALL_PROGRAM) foo $(bindir)/foo
$(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a

항상 설치 명령들의 두번째 매개변수로써 파일 이름을 사용하고 디렉토리 이름을 사용하지 말자. 설치되는 각 파일에 대해서 분리된 명령을 사용하자.

설치 디렉토리들을 위한 변수(Variables for Installation Directories)

설치 디렉토리들은 항상 변수들에 그 이름을 갖고 있어서 비표준 위치에 설치하는 것이 쉬워야 한다. 이런 변수들을 위한 표준 이름들이 아래에 설명될 것이다. 그들은 표준 파일 시스템 레이아웃에 기반한다: 이것이 변종들이 SVR4, 4.4BSD, Linux, Ultrix v4, 그리고 다른 현대 운영체제들에서 사용된다.

이런 두 변수들은 설치를 위한 루트 디렉토리를 설정한다. 모든 다른 설치 디렉토리들은 이들 중 하나의 서브디렉토리이어야 하고 어떤 것도 이런 두 디렉토리에 직접 설치되어서는 안된다.

`prefix'
prefix 는 아래에 나온 변수들의 디폴트값들을 구축할 때 사용된다. prefix 의 디폴트 값은 `/usr/local' 이어야 한다. 완전한 GNU 시스템을 설치할 때, prefix 는 빈 것이 될 것이고 `/usr'`/' 에 심볼릭 링크가 될 것이다. (Autoconf 를 사용한다면 이것을 `@prefix@' 에 써넣으면 된다.)
`exec_prefix'
아래에 나오는 변수들 몇가지의 디폴트 값들을 구축하는 데 사용되는 접두사. exec_prefix 의 디폴트 값은 $(prefix) 이어야 한다. (Autoconf 를 사용하고 있다면 이것을 `@exec_prefix@' 로 쓰자.) 일반적으로 $(exec_prefix) 는 기계-종속적인 파일들(실행 파일들과 서브루틴 라이브러리들과 같은)을 담고 있는 디렉토리들에 사용된다. 반면에 $(prefix) 는 다른 디렉토리들에 사용된다.

실행 프로그램들은 다음과 같은 디렉토리들 중의 하나에 설치된다.

`bindir'
사용자들이 실행할 수 있는 실행 프로그램들을 설치하기 위한 디렉토리. 이것은 일반적으로 `/usr/local/bin' 이지만 `$(exec_prefix)/bin' 로 작성하여야 한다. (Autoconf 를 사용하고 있다면 이것을 `@bindir@' 로 쓰자.)
`sbindir'
쉘로부터 실행 가능하지만 시스템 어드민들에게만 보통 유용한, 실행 프로그램들을 설치하기 위한 디렉토리. 이것은 보통 `/usr/local/sbin' 이지만 `$(exec_prefix)/sbin' 로 작성해야 한다. (Autoconf 를 사용하고 있다면 이것을 `@sbindir@' 로 작성하자.)
`libexecdir'
사용자들이 아니라 다른 프로그램들에 의해서 실행되는 실행가능 프로그램들을 설치하기 위한 디렉토리. 이 디렉토리는 보통 `/usr/local/libexec' 이지만 이것을 `$(exec_prefix)/libexec' 로 쓰자. (Autoconf 를 사용하고 있다면 이것을 `@libexecdir@' 로 쓰자.)

실행 동안 프로그램에 의해서 사용되는 데이터 파일들은 다음과 같은 두 가지 방법으로 분류될 수 있다.

이것은 여섯가지 다른 가능성들을 만든다. 그러나 오브젝트 파일들과 라이브러리들을 제외하고, 아키텍쳐-종속적인 파일들을 사용하지 않기를 권하고 싶다. 데이터 파일들을 아키텍쳐-독립으로 만드는 것이 더 선명하다. 그리고 이렇게 하는 것은 일반적으로 그리 어렵지 않다.

그래서 Makefile 들이 디렉토리들을 지정하는 데 사용하여야 할 변수들을 다음에 놓았다:

`datadir'
읽기-전용 아키텍쳐 독립 데이터 파일들을 설치하는 디렉토리. 이것은 일반적으로 `/usr/local/share' 이어야 한다. 그러나 이것을 `$(prefix)/share' 로 쓴다. (Autoconf 사용자라면 이것을 `@datadir@' 으로 쓴다.) 특별한 예외로써 아래의 `$(infodir)'`$(includedir)' 을 보자.
`sysconfdir'
단일 기계에 대해서(만) 관계된 읽기-전용 데이터 파일을 설치하기 위한 디렉토리--즉, 호스트를 설정하기 위한 파일들의 디렉토리. 메일러나 네트우거 설정 파일들, `/etc/passwd', 그리고 기타 등등이 여기에 해당된다. 이 디렉토리에 있는 모든 파일들은 일반 ASCII 텍스트 파일들이어야 한다. 이 디렉토리는 일반적으로 `/usr/local/etc' 이지만, 이것을 `$(prefix)/etc' 로 쓴다. (Autoconf 를 쓰고 있다면 이것을 `@sysconfdir@' 로 작성하다.) 실행파일들을 이런 디렉토리에 설치하지 말자(그들은 아마도 `$(libexecdir)'`$(sbindir)' 에 속할 것이다). 또한 그들 사용(그것의 목적이 시스템의 설정을 배타적으로 변경하는 프로그램)의 일반저인 과정에서 파일이 변경되는 파일들은 설치하지 말자. 이들은 아마도 `$(localstatedir)'에 포함될 것이다.
`sharedstatedir'
프로그램들이 실행 중에 변경하는 아키텍쳐-독립 데이터 파일들을 설치하는 디렉토리. 이것은 일반적으로 `/usr/local/com' 이어야 하지만 이것을 `$(prefix)/com' 로 쓰자. (Autoconf 를 사용하고 있다면 이것을 `@sharedstatedir@' 로 쓰자.)
`localstatedir'
프로그램들이 실행 중에 변경하는 데이터 파일들을 설치하기 위한, 그리고 특정 기계에만 있는, 디렉토리. 사용자들은 팩키지의 작동을 설정하기 위해서 이 디렉토리에 있는 파일들을 변경할 필요가 전혀 없다; 그런 설정 정보는 독립 파일들 `$(datadir)'`$(sysconfdir)' 에 넣도록 하자. `$(localstatedir)' 는 보통 `/usr/local/var' 이어야 하지만 이것을 `$(prefix)/var' 로 쓰자. (Autoconf 를 사용하고 있다면 이것을 `@localstatedir@' 로 쓰자.)
`libdir'
오브젝트 파일들과 오브젝트 코드의 라이브러리들을 위한 디렉토리. 실행 파일들을 이곳에 설치하지 말자. 그들은 아마도 `$(libexecdir)' 에 가게 될 것이다. libdir 는 보통 `/usr/local/lib' 이어야 하지만 이것을 `$(exec_prefix)/lib' 로 쓰자. (Autoconf 를 사용하고 있다면 이것을 `@libdir@' 로 쓰자.)
`infodir'
해당 팩키지를 위한 Info 파일들을 설치하기 위한 디렉토리. 디폴트로 이것은 `/usr/local/info' 이어야 하지만 `$(prefix)/info' 로 작성되저야 한다. (Autoconf 를 사용하고 있다면 `@infodir@' 로 작성하자.)
`lispdir'
이맥스 Lisp 파일들을 설치하기 위한 디렉토리. 디폴트로 이것은 `/usr/local/share/emacs/site-lisp' 이지만 `$(prefix)/share/emacs/site-lisp' 로 작성되어야 한다. Autoconf 를 사용하고 있다면 디폴트를 `@lispdir@' 로 작성한다. `@lispdir@' 가 작동하도록 만들려면 다음과 같은 라인들을 여러분의 `configure.in' 파일에 넣을 필요가 있다:
lispdir='${datadir}/emacs/site-lisp'
AC_SUBST(lispdir)
`includedir'
C 의 `#include' 선행처리 지시어로 사용자 프로그램에 의해서 포함될 헤더 파일들을 설치하기 위한 디렉토리. 이것은 보통 `/usr/local/include' 이어야 하지만 이것을 `$(prefix)/include' 로 쓰자. (Autoconf 를 사용하고 있다면 이것을 `@includedir@' 로 쓰자.) GCC 가 아닌 대부분의 컴파일러들은 헤더 파일들을 `/usr/local/include' 디렉토리에서 찾지 않는다. 그래서 헤더 파일들을 이런 식으로 설치하는 것은 GCC 의 경우에만 유용하다. 때때로 이것은 어떤 라이브러리들이 실제 GCC 와만 작동하게끔 고안되었기 때문에 문제가 되지 않는다. 그러나 어떤 라이브러리들은 다른 컴파일러들과도 작동하게끔 고안된 것이 있을 수 있다. 그들은 그들의 헤더 파일들을 하나는 includedir 에 그리고 하나는 oldincludedir 에 설치함으로써 두 곳에 설치해야 한다.
`oldincludedir'
GCC 가 아닌 컴파일러들을 위한 `#include' 헤더 파일들을 설치하는 디렉토리. 이것은 보통 `/usr/include' 이어야 한다. (Autoconf 를 사용하고 있다면 여러분은 이것을 `@oldincludedir@' 로 쓰자.) Makefile 명령들은 oldincludedir 이 빈 값인가 아닌가를 체크해야 한다. 그렇다면 그들은 이것을 사용하려고 시도해서는 안된다; 그들은 헤더 파일들의 두번째설치를 취소해야 할 것이다. 헤더가 동일한 팩키지로부터 온 것이 아니라면 이 디렉토리에 기존에 있던 헤더를 교체해서는 안된다. 그래서 Foo 라는 팩키지가 헤더 파일 `foo.h' 를 제공한다면, (1) `foo.h' 파일이 거기에 없거나 (2) `foo.h' 이 존재하지만 Foo 팩키지로부터 온 것이라면, oldincludedir 디렉토리에 그 헤더파일을 설치해야 한다. `foo.h' 이 Foo 팩키지로부터 온 것인가를 알아내려면 매직 문자열을 그 파일 안에 넣자---주석의 일부---그리고 그 문자열을 grep 한다.

유닉스-스타일 맨 페이지들은 다음과 같은 것 중의 하나로 설치된다:

`mandir'
맨 페이지들(존재한다면)을 설치하기 위한 톱-레벨 디렉토리. 이것은 보통 `/usr/local/man' 이어야 하지만 이것을 `$(prefix)/man' 로 써야 한다. (Autoconf 를 사용하고 있다면, 이것을 `@mandir@' 로 쓰자.)
`man1dir'
섹션 1 맨 페이지들을 설치하기 위한 디렉토리. 이것을 `$(mandir)/man1' 로 쓰자.
`man2dir'
섹션 2 맨 페이지들을 설치하기 위한 디렉토리. 이것을 `$(mandir)/man2' 로 쓰자.
`...'
GNU 소프트웨어에 대한 주 문서를 맨 페이지로 만들지 말자. 대신에 Texinfo 포멧으로 매뉴얼을 작성하자. 맨 페이지들은 GNU 소프트웨어를 Unix 에서 실행하는 사람들을 위한 것이다. 이것은 우선순위 두번째의 것일 뿐이다.
`manext'
설치된 맨 페이지에 대한 파일 이름 확장자. 이것은 소숫점과 적절한 숫자를 가지고 있어야 한다; 이것은 보통 `.1' 일 것이다.
`man1ext'
설치된 섹션 1 맨 페이지들을 위한 파일 이름 확장자.
`man2ext'
설치된 섹션 2 맨 페이지들을 위한 파일 이름 확장자.
`...'
팩키지가 맨 페이지들을 여러 섹션에 설치해야 한다면, 이런 이름들을 `manext' 대신에 사용하자.

그리고 마지막으로 다음과 같은 변수를 설정해야 할 것이다:

`srcdir'
컴파일되는 소스들을 위한 디렉토리. 이 변수의 값은 보통 configure 쉘 스크립트에 의해서 삽입된다. (Autoconf 를 사용하고 있다면 `srcdir = @srcdir@' 를 쓰자.)

예를 들어서:

# Common prefix for installation directories.
# NOTE: This directory must exist when you start the install.
prefix = /usr/local
exec_prefix = $(prefix)
# Where to put the executable for the command `gcc'.
bindir = $(exec_prefix)/bin
# Where to put the directories used by the compiler.
libexecdir = $(exec_prefix)/libexec
# Where to put the Info files.
infodir = $(prefix)/info

많은 개수의 파일들을 표준 사용자-지정 디렉토리들 중의 하나로 설치한다면 그것들을 그 프로그램만의 서브디렉토리로 묶어 주는 것이 유용할 것이다. 이렇게 한다면 이런 서브디렉토리들을 만들기 위한 install 규칙을 작성해야 할 것이다.

사용자가 위에 나온 변수들 중의 하나의 값으로 서브디렉토리 이름을 포함할 것이라고 기대하지 말자. 설치 디렉토리들을 위한 일관된 변수 이름들을 가질려는 생각은, 사용자가 여러 서로 다른 GNU 팩키지들에 대해서 정확히 동일 값들을 지정할 수 있게 하기 위해서이다. 이것이 유용하기 위해서는 사용자가 그렇게 할 때 모든 팩키지들이 현명하게 작동하도록 잘 설계되어야 한다.

사용자들을 위한 표준 타겟(Standard Targets for Users)

모든 GNU 프로그램들은 다음과 같은 타겟들을 그들의 makefile 안에 가져야 한다:

`all'
전체 프로그램을 컴파일한다. 이것은 디폴트 타겟이어야 한다. 이 타겟은 문서 파일들을 다시 빌드할 필요는 없다; Info 파일들은 일반적으로 배포판 안에 포함되어야 하고, DVI 파일들은 사용자에 의해서 명시적으로 요구될 때에만 만들어져야 한다. 디폴트로 Make 규칙들은 `-g' 옵션으로 컴파일하고 링크해서 그 실행 프로그램들이 디버깅 심벌들을 가지도록 해야 한다. 무력해지는 것에 신경쓰지 않는 사용자들은 그들이 원할 때 그 실행파일들을 strip 할 수 있다.
`install'
프로그램을 컴파일하고 실행 파일들과 라이브러리들, 기타 등등을 이들이 실제 사용을 위해서 위치해야 할 곳에 파일 이름들로 복사한다. 어떤 프로그램이 적절하게 설치되었는가를 검증하기 위한 단순한 테스트가 있다면 이 타겟은 그 테스트를 실행해야 한다. 실행파일들을 설치할 때 그들을 strip하지 말자. 아주 태평스러운 사용자들은 그렇게 하기 위해서 install-strip 를 사용할 수있다. 가능하다면 install 타겟 규칙이 프로그램이 빌드되는 디렉토리에서, `make all' 이 방금 수행되었다면, 아무것도 변경하지 않도록 작성하자. 이것은 프로그램을 한 유저가 빌드하고 그것을 다른 유저가 설치하는 경우에 좋다. 명령들은 파일들이 설치될 모든 디렉토리들을 그들이 앞서 존재하지 않는다면 생성해야 한다. 이것은 prefixexec_prefix 변수들의 갑들로 지정된 디렉토리들과 필요한 모든 서브디렉토리들을 포함한다. 이렇게 하기 위한 한가지 방법은 아래에 설명된 installdirs 타겟을 사용하는 것이다. 맨 페이지를 설치하기 위한 임의의 명령 앞에다 `-' 를 사용해서 make 가 임의의 에러들을 무시하도록 하자. 이것은 설치된 유닉스 맨 페이지 문서 시스템을 가지지 않는 시스템들이 있는 경우를 위한 것이다. Info 파일들을 설치하는 방법은 이들을 `$(infodir)' 에다 $(INSTALL_DATA) 로 (see section 명령을 지정하기 위한 변수(Variables for Specifying Commands)) 복사하고 install-info 프로그램이 존재한다면 이것을 실행하는 것이다. install-info 는 Info `dir' 파일을 편집해서 주어진 Info 파일을 위한 메뉴 엔트리를 추가하거나 갱신하는 프로그램이다; 이것은 Texinfo 팩키지의 일부이다. 다음은 Info 파일을 설치하는 예제 규칙이다:
$(infodir)/foo.info: foo.info
        $(POST_INSTALL)
# There may be a newer info file in . than in srcdir.
        -if test -f foo.info; then d=.; \
         else d=$(srcdir); fi; \
        $(INSTALL_DATA) $$d/foo.info $@; \
# Run install-info only if it exists.
# Use `if' instead of just prepending `-' to the
# line so we notice real errors from install-info.
# We use `$(SHELL) -c' because some shells do not
# fail gracefully when there is an unknown command.
        if $(SHELL) -c 'install-info --version' \
           >/dev/null 2>&1; then \
          install-info --dir-file=$(infodir)/dir \
                       $(infodir)/foo.info; \
        else true; fi
install 타겟을 작성할 때, 모든 명령들을 다음과 같은 세 범주들로 분류해야 한다: 일반 명령, 설치-이전(pre-installation) 명령, 그리고 설치-이후(post-installation) 명령. See section 설치 명령 범주(Install Command Categories).
`uninstall'
모든 설치된 파일들을 삭제한다---`install' 타겟이 생성한 복사물들. 이 규칙은 컴파일이 수행된 디렉토리들을 변경해서는 안된다. 파일들이 설치된 디렉토리들만 변경해야 한다. 설치 제거 명령들은 설치 명령들과 같이 세개의 범주들로 나뉜다. See section 설치 명령 범주(Install Command Categories).
`install-strip'
install 와 같지만 실행 파일들을 설치할 때 이들의 심벌들을 제거한다. 많은 경우에 이 타겟의 정의는 다음처럼 아주 단순할 수 있다:
install-strip:
        $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
                install
보통 프로그램이 버그가 없다는 것을 확신하지 못한다면 실행 파일의 심벌들을 제거하는 것을 권장하고 싶지 않다. 그러나 버그가 있을 경우를 대비해서 심벌들을 제거하지 않는 실행파일을 어딘가에 저장하고 실제 실행 파일은 심벌들을 제거해서 설치하는 것도 합리적일 수 있다.
`clean'
보통 프로그램을 빌드하면서 생성되는, 현재 디렉토리에 있는, 모든 파일들을 제거한다. 환경설정을 길고한 파일들은 지우지 않는다. 또한 빌드에 의해서 생성될 수 있지만 보통은 만들어지지 않는 파일들을, 배포판이 그들을 담고 있기 때문에, 보존한다. `.dvi' 파일들이 배포판의 일부가 아니라면 이들을 지워라.
`distclean'
현재 디렉토리로부터 환경 설정과 프로그램 빌드 과정에 의해서 생성된 모든 파일들을 지운다. 소스를 unpack 했고 그 프로그램을 다른 파일들을 생성하지 않고서 빌드했다면 `make distclean' 는 배포판에 있었던 파일들만을 지울 것이다.
`mostlyclean'
`clean' 과 비슷하지만 사람들이 보통 재컴파일하고자 하지 않는 몇가지 파일들을 삭제하지 않을 수 있다. 에를 들어서 GCC 를 위한 `mostlyclean' 타겟은 `libgcc.a' 를 삭제하지 않는다. 왜냐면 이것을 재컴파일하는 것은 거의 필요가 없고 시간만 많이 걸리기 때문이다.
`maintainer-clean'
현재 디렉토리로부터, Makefile 로 다시 만들어질 수 있는 거의 모든 것을 삭제한다. 이것은 전형적으로 distclean 로 삭제되는 모든 것과 그 외의 것들을 포함한다: Bison 에 의해서 만들어진 C 소스 파일, 태그 테이블, Info 파일들, 기타 등등. 우리가 "거의 모든것" 이라고 말한 이유는 명령 `make maintainer-clean' 를 실행하는 것은 `configure' 가 Makefile 의 한 규칙을 사용해서 만들어질 수 있다고 하더라도, `configure' 를 지우지 않을 것이기 때문이다. 좀 더 일반적으로 `make maintainer-clean'`configure' 를 실행하기 위해서 존재해야 하는 어떤 것도 지우지 않고 프로그램을 빌드하기 시작하는 어떤 것도 지우지 않는다. 이것은 유일한 예외이다; maintainer-clean 는 다시 빌드될 수 없는 다른 모든 것들을 삭제할 것이다. `maintainer-clean' 타겟은 일반 사용자들에 의해서가 아니라 팩키지의 관리자에 의해서 사용될 것으로 고안된 것이다. `make maintainer-clean' 가 삭제한 파일들 몇가지를 재건축하려면 특수한 툴들이 필요할 수 있다. 이런 파일들은 일반적으로 배포판 안에 포함되기 때문에 우리는 그들이 다시 만들어지기 쉽도록 신경쓰지 않는다. 전체 배포판을 다시 unpack 하는 것이 필요하다고 생각되더라도 우리를 원망하지 말라. 사용자들이 이런 것을 알도록 하기 위해서 특수 maintainer-clean 타겟의 명령들은 다음과 같은 두 라인으로 시작해야 한다.
@echo 'This command is intended for maintainers to use; it'
@echo 'deletes files that may need special tools to rebuild.'
`TAGS'
이것은 프로그램에 대한 태그 테이블을 갱신한다.
`info'
필요한 임의의 Info 파일들을 생성한다. 규칙을 작성하는 가장 좋은 방법은 다음과 같은 것이다:
info: foo.info

foo.info: foo.texi chap1.texi chap2.texi
        $(MAKEINFO) $(srcdir)/foo.texi
변수 MAKEINFO 는 반드시 Makefile 안에서 정의해야 한다. 이것은 makeinfo 프로그램을 실행해야 하며, 이것은 Texinfo 배포판의 일부이다. 일반적으로 GNU 배포판은 Info 파일들이 따라 온다. 즉 Info 파일들이 소스 디렉토리에 존재한다는 것을 의미한다. 그러므로 info 파일을 위한 Make 규칙은 그것을 소스 디렉토리에서 갱신해야 할 것이다. 사용자가 팩키지를 빌드할 때 일반적으로 Make 는 Info 파일들을 갱신하지 않을것이다. 왜냐면 그들이 이미 갱신되었을 것이기 때문이다.
`dvi'
모든 Texinfo 문서들에 대해서 DVI 파일들을 생성한다. 예를 들어서:
dvi: foo.dvi

foo.dvi: foo.texi chap1.texi chap2.texi
        $(TEXI2DVI) $(srcdir)/foo.texi
반드시 Makefile 안에 TEXI2DVI 변수를 정의해야 한다. 이것은 texi2dvi 를 반드시 실행해야 한다. 이것은 Texinfo 배포판의 일부 (texi2dvi는 TeX 를 사용해서 포멧팅의 실제 작업을 수행한다. TeX 는 Texinfo 와 함께 배포되지 않는다) 이다. 또는, 단지 종속물들만 써서 GNU make 가 그 명령을 제공하도록 하자.
`dist'
이 프로그램에 대한 배포판 tar 파일을 생성한다. tar 파일은 tar 파일안의 파일 이름들이 팩키지가 배포되는, 그리고 팩키지의 이름인, 서브디렉토리 이름으로 시작하게끔 설정되어야 한다. 이 이름은 버전 이름을 포함할 수 있다. 예를 들어서 GCC 버전 1.40 의 배포판 tar 파일은 `gcc-1.40' 라는 이름의 서브디렉토리로 압축이 풀린다. 이렇게 하기 위한 가장 쉬운 방법은 적절하게 이름을 붙인 서브디렉토리를 생성하고 ln 이나 cp 를 사용해서 적절한 파일들을 그 디렉토리 안으로 설치하고, 그리고 나서 그 서브디렉토리를 tar 하는 것이다. 그 tar 파일을 gzip 으로 압축하자. 예를 들어서 GCC 버전 1.40 을 위한 실제 배포판 파일은 `gcc-1.40.tar.gz' 이 될 것이다. dist 타겟은, 배포판에서 그들이 갱신된 것이라는 것을 확실하게 하기 위해서, 반드시 명시적으로 배포판에 있는 모든 소스가 아닌 파일들에 의존해야 한다. See section `Making Releases' in GNU Coding Standards.
`check'
자체-테스트(만일 있다면)를 수행한다. 사용자는 테스트를 수행하기 전에 반드시 프로그램을 빌드해야 한다. 그러나 그 프로그램을 설치할 필요는 없다; 그 프로그램이 빌드되었지만 인스톨되지 않았더라도 잘 작동하도록 자체-테스트들을 작성해야 한다.

다음 타겟들은 관례적인 이름들로 제안된 것이다.

installcheck
설치 테스트(만일 있다면)를 수행한다. 사용자는 이 테스트를 수행하기 전에 반드시 빌드해야 하고 설치해야 한다. `$(bindir)' 디렉토리가 검색 경로에 있을 것이라고 가정해서는 안된다.
installdirs
파일들이 설치되는 디렉토리들과 그들의 부모 디렉토리들을 생성하기 위한 `installdirs' 라는 이름의 타겟을 추가하는 것이 유용하다. 이런 것에 편리한 `mkinstalldirs' 라고 불리는 스크립트가 존재한다; 이것은 Texinfo 팩키지에서 찾을 수 있다. 여러분은 다음과 같은 규칙을 사용할 수 있다:
# Make sure all installation directories (e.g. $(bindir))
# actually exist by making them if necessary.
installdirs: mkinstalldirs
        $(srcdir)/mkinstalldirs $(bindir) $(datadir) \
                                $(libdir) $(infodir) \
                                $(mandir)
이 규칙은 컴파일이 수행된 디렉토리들을 변경해서는 안된다. 이것은 설치 디렉토리들을 생성하는 일만 해야 한다.

설치 명령 범주(Install Command Categories)

install 타겟을 작성할 때, 모든 명령들을 다음과 같은 세가지 범주로 분류해야 한다: 정규적인 것, 설치-이전(pre-installation) 명령어들, 그리고 설치-이후(post-installation) 명령어들.

정규 명령어들은 파일들을 그들의 적절한 위치에 옮기고, 그들의 모드를 설정한다. 그들은 이들이 속한 팩키지로부터 전체적으로 오는 것들을 제외하고는 어떤 파일들도 변경하지 않는다.

설치-이전과 설치-이후 명령들은 다른 파일들을 변경할 수도 있다; 특별히 그들은 글로벌 설정 파일들이나 데이터 베이스들을 편집할 수 있다.

설치-이전 명령어들은 전형적으로 정규 명령들 이전에 실행되고, 설치-이후 명령어들은 전형적으로 정규 명령어들 이후에 실행된다.

설치-후 명령에 대한 대부분의 일반적인 사용은 install-info 를 실행하는 것이다. 이것은 일반적인 명령으로 실행될 수 없다. 왜냐면 이것은 설치중인 팩키지로부터 완전히 그리고 이것으로부터만 온 것이 아닌 파일(Info 디렉토리)을 변경하기 때문이다. 팩키지의 Info 파일들을 설치하는 일반 명령 뒤에 수행되어야 하기 때문에 이것은 설치-이후 명령이다.

대부분의 프로그램들은 어떤 설치-이전 명령들을 필요로하지 않는다. 그러나 필요할 때를 대비해서 그 기능을 가지고 있다.

install 규칙에 있는 명령들을 이런 세가지 범주들로 구분하기 위해서 그들 사이에 범주 라인(category lines) 를 삽입하자. 범주 라인은 그 뒤에 오는 명령들에 대한 범주를 지정한다.

범주 라인은 하나의 탭과 특정 Make 변수에 대한 참조, 그리고 마지막에 옵션인 주석으로 이루어져 있다. 사용할 수 있는 변수들은 세개 있으며 이들 각각은 각 범주를 위한 것이다; 변수 이름이 범주를 지정한다. 범주 라인들은 일반적인 실행에서는 아무런 작동도 하지 않는다. 왜냐면 이런 세 Make 변수들은 일반적으로 정의되지 않기 때문이다(그리고 여러분은 그것들을 makefile 안에서 정의해서는 안된다).

다음은 가능한 세가지 범주 라인들이며 이들 각각은 그것이 의미하는 바를 설명하는 주석을 달고 있다:

        $(PRE_INSTALL)     # Pre-install commands follow.
        $(POST_INSTALL)    # Post-install commands follow.
        $(NORMAL_INSTALL)  # Normal commands follow.

install 규칙의 처음에 범주 라인을 쓰지 않는다면 모든 명령들은 첫번째 범주 라인 이전까지 일반으로 구분된다. 범주 라인들을 전혀 사용하지 않는다면 모든 명령들이 일반으로 구분된다.

다음이 uninstall 에 대한 범주 라인들이다:

        $(PRE_UNINSTALL)     # Pre-uninstall commands follow.
        $(POST_UNINSTALL)    # Post-uninstall commands follow.
        $(NORMAL_UNINSTALL)  # Normal commands follow.

전형적으로 설치-이전 명령은 Info 디렉토리로부터 항목들을 지우는 일을 하는 데 사용된다.

install 또는 uninstall 타겟이 설치의 서브루틴들처럼 작동하는 종속물들을 가지고 있다면 종속물의 명령들을 범주 라인으로 시작해야 하고 메인 타겟의 명령들도 범주 라인으로 시작해야 한다. 이런식으로 어떤 종속물들이 실제로 실행되든지 상관없이, 정확한 범주안에 놓여 있다는 것을 보장할 수 있다.

설치-이전 및 설치-이후 명령들은 다음과 같은 것들을 제외한 프로그램들을 실행해서는 안될것이다:

[ basename bash cat chgrp chmod chown cmp cp dd diff echo
egrep expand expr false fgrep find getopt grep gunzip gzip
hostname install install-info kill ldconfig ln ls md5sum
mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee
test touch true uname xargs yes

이런식으로 명령들을 구분하는 이유는 바이너리 팩키지를 만들기 위해서이다. 전형적으로 바이너리 팩키지는 모든 실행파일들과 설치에 필요한 다른 파일들을 담고 있고, 이 설치에 필요한 파일들을 설치하는 자신의 방법을 갖고 있다---그래서 이것은 일반적인 설치 명령들이 필요없다. 그러나 바이너리 팩키지를 설치하는 것은 설치-이전과 설치-이후 명령들을 실행할 필요가 있다.

바이너리 팩키지들을 빌드하는 프로그램들은 설치-이전 및 설치-이후 명령들을 추출함으로써 작동한다. 다음은 설치-이전 명령들을 추출하는 한가지 방법이다:

make -n install -o all \
      PRE_INSTALL=pre-install \
      POST_INSTALL=post-install \
      NORMAL_INSTALL=normal-install \
  | gawk -f pre-install.awk

여기에서 `pre-install.awk' 는 다음과 같은 것을 담고 있을 것이다:

$0 ~ /^\t[ \t]*(normal_install|post_install)[ \t]*$/ {on = 0}
on {print $0}
$0 ~ /^\t[ \t]*pre_install[ \t]*$/ {on = 1}

설치-이전 명령들의 결과 파일은, 바이너리 팩키지를 설치하는 일부인 쉘 스크립트로써 실행된다.


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