7. 간단한 예제 - minimal project

작은 예제를 통해서 autotool 을 사용하는 방법을 보이겠습니다.

흔히 가장 작은 예로 hello.c 를 autotool 을 이용하여 컴파일하고 install 하는 예를 많이 들어보이고 있는데 여기서는 이보다 조금 더 autoconf automake 의 능력을 발휘할 수 있는 예를 들어 보이겠습니다.

흔히 open source project 를 할때 현재 install 하고자 하는 machine 에 상관없이 configure, make, make install 을 통해서 간단하게 프로그램을 install 할수 있었는데 여기서는 이를 간단히 구현해보고자 합니다.더군다나 project 진행상 가장 기본적으로 필요한 기능입니다.

간단히 하기 위해 solaris 와 linux 에 대해서만 보이겠습니다.solaris 에서 실행될 파일과 linux 에서 실행될 파일이 필요합니다. 물론 같은 기능을 하는 파일로 같은 이름을 사용하여도 상관없습니다.

이들이 놓이게 될 장소와 이들을 가지고 원하는 작업을 수행하게 될 autotools 관련 파일들이 놓이게 될 위치를 아래에서 보이도록 하겠습니다.

7.1. 소스의 위치

소스들(solaris 에서 실행될 파일은 solaris.c 라 하고 linux 에서 실행될 파일을 linux.c 라고 하자.) 을 배치 할때는 운영체제 별로 directory 를 만들어서 관리하는 것이 좋다.(현재 가장 중요한 구분요소는 운영체제별로 build 가 이루어지게 하는 것이기 때문이기도 하다.) solaris.c 는 solaris directory 에 linux.c 는 linux directory 에 보관한다.

. project directory
./solaris/solaris.c
./linux/linux.c

project directory 에서 각각의 program source 들이 위치할수 있는곳은 바로 하나 아래의 dirctory 까지 이다. 즉 depth 1 의 directory 만 허용되며 그 이상의 깊이를 가지는 directory 안에 있는 소스에 대해서는 configure 로 Makefile 을 만들수 없어 실제로는 autoconf, automake 를 이용하기 위해서는 각 소스들은 depth 1 의 directory 에만 위치해야 한다. 이 문제는 automake 1.4 를 사용할 경우 고려되어야 하며 1.5 이후의 버젼에서는 이 문제가 해결되었다. 1.5 이상의 automake 를 사용하고 있다면 subdirectory 에 위치한 소스에 대해서도 makefile을 만들수 있고 subdirectory 의 파일을 상위 directory 에서 불러와 사용 할 수 있게 되었다.

7.2. autotools 입력 화일들의 위치

autoconf 의 입력화일인 configure.ac 는 project directory 에 위치하도록 한다. 즉 가장 상위 directry 에 위치하도록 하고 automake 의 입력파일이면서 configure 의 입력값이 될 Makefile.am 은 각각의 소스가 위치한 곳에 놓도록 한다. 이 Makefile.am 들이 각 소스에 대한 Makefile 이 된다고 생각할때 이 위치에 대한 이견은 없을것이다.

. project directory
./configure.ac
./Makefile.am

./solaris/solaris.c
./solaris/Makefile.am

./linux/linux.c
./linux/Makefile.am

이제 각 directory 에 위치한 configure.ac, Makefile.am 이 어떻게 작동하는 지 살펴보자.

7.3. 최상위 directory 의 Makefile.am 의 역할

최상위 directory의 Makefile.am 은 configure 시 build 할 directory 를 판단한다. SUBDIRS 라는 변수를 가지고 있으며 여기에 지정된 directory 에 대해 Makefile.am 을 가지고 Makefile 을 만들게 된다. 우리는 configure 결과에 따라 시스템이 solaris 인지 linux 인지를 판단하여, solaris directory 를 build 할 것인 지 linux directory 를 build 할 것인지를 정해야 한다.즉 이 SUBDIRS 는 configure 시에야 알 수 있는 값이므로 일단 적당한 변수로 두고 configure 시 유효한 값으로 치환되도록 해야한다.

configure 시 build directory 를 결정하도록 하며 이 directory 의 값을 DIRS 라는 변수에 저장하도록 하고, 최상의 Makefile.am 에서는 이 값을 가져다 쓰기 위해 다음과 같이 쓰면 된다.

SUBDIRS=@DIRS@

이제 configure 에서 이 DIRS 값을 어떻게 결정하고 Makefile.am 에 넘겨주는지 보도록 한다.

7.4. configure.ac 의 역할

configure시에 많은 정보를 얻어야 하며 이를 바탕으로 Makefile이 만들어 진다고 할때 configure 시에 check 해야 할것들을 미리 정해주는 configure.ac 의 역할이 autotools 사용의 효용성을 결정한다고 할수도 있다. 각각의 check 사항들은 macro 로 정의되어 있으며 그에 대해서는 필요할경우마다 하나씩 찾아가면서 공부할수있다. 즉 하나의 macro 를 알고 모르는것이 그렇게 중요하지는 않으며 원하는 check 사항이 생길때마다 macro 를 조사하는 것으로도 가능하다.

이번 예에서는 각 platform 별로 build 하기를 원하기 때문에 configure 시 현재의 platform 을 알아야 하고 이를 바탕으로 build 할 subdirectory, 즉 최상위 Makefile.am 에서 SUBDIRS 에 들어가게될 DIRS 의 값을 결정해 주어야 한다. 기본적인 여러 macro 들이 있겠지만 일단 이과정이 어떻게 처리되는지를 보자.

AC_CANONICAL_SYSTEM

case "$target" in
	i?86-*-linux*)
		DIRS="linux" ;
		AC_SUBST(DIRS)
		;;
	*solaris*)
		DIRS="solaris" ;
		AC_SUBST(DIRS)
		;;
	*)
		echo unsupported system : $target
		;;
esac

AC_CANONICAL_SYSTEM 이라는 macro 를 통해서 target 이라는 shell 변수에 현재 system 의 정보를 기록하게 된다. 이 정보는 configuration name 형식으로 cpu-manufacturer-operation_system 으로 구성되며, 위의 case 문은 이를 바탕으로 쓰여졌다. 즉 AC_CANONICAL_SYSTEM 이라는 macro 의 실행결과 생긴 target 변수의 내용을 바탕으로 target 에 따른 행동을 할 수 있게 된다.

이제 case 문 안으로 들어가면 DIRS 라는 변수에 linux 또는 solaris 를 assign 하고 이를 AC_SUBST() macro 를 통해 대치시키고 있다. 이 macro 는 parameter 로받은 변수에 대해 Makefile.am 이나 *.in 에서 이 변수명을 쓰는 값들을 현재 assign 한 값으로 대치시켜 준다. 이번 예제의 경우는 최상위 directory의 Makefile.am 에서 SUBDIRS=@DIRS@ 의 DIRS 의 값을 바꾸게 된다.

따라서 configure 를 거치게 되면 최상위 Makefile.am 의 SUBDIRS 에는 해당 머신에따라 linux 혹은 solaris 가 들어가게 된다. 편의상 현재 configure 가 일어나고 있는 머신을 linux 라고 할때 SUBDIRS=linux 가 되어서 make 를 하게 될 경우 이 Makefile (최상위 directory 의 Makefile.am 에서 만들어지는 Makefile) 에 의해 linux directory 만 빌드가 이루어 지게 된다. solaris directory 에 대한 빌드는 이루어지지 않으며 따라서 platform 을 따져서 원하는 source 를 빌드할수 있게 된다.

7.5. 하부 directory 의 Makefile.am 의 역할

기본적인 사용을 위해서는 다음 두줄로도 춤분합니다.

./linux/Makefile.am

bin_PROGRAMS = linux
linux_SOURCES = linux.c

기본적으로 Makefile.am 에도 쓸수 있는 값들이 정해져 있다. _PROGRAMS, _SCRIPTS, _DATA, _SOURCES primry 들을 쓸 수 있는데 undersquare 앞에 특정 directory 를 정해 주어야 하는데 이 directory 가 해당 프로그램이나 파일들이 install 될 위치를 가르킨다. 위의 Makefile.am 에서는 linux.c 파일을 compile 해서 linux 라는 이름의 프로그램으로 만든후 이를 bin directory 에 install 하게 된다.

여기서 bin directory는 위의 configure.ac 에서 정의된 default prefix 아래의 bin directory 를 가르키게 된다. 즉, configure.ac 에서

AC_PREFIX_DEFAULT(/usr/eostk)

라고 정의하였다면, 이 bin 은 /usr/eosrk/bin 이 되고 linux 프로그램은 그 아래에 install 된다.

_SCRIPTS 는 script 를 install 하기 위해 쓰이고 _DATA 는 그냥 파일들을 install 하게 될 경우에 쓰인다. 둘다 _SOURCES 를 필요로 하지 않기 때문에 비슷하나 _SCRIPTS 는 실행 가능하고 _DATA 는 실행불가능하기때문에 따로 쓰고 있다.

이렇게 쓰여진 Makefile.am 은 configure 시 최상위 Makefile.am 에서 지정하는 SUBDIRS 에 포함될 경우만 build 가 이루어지는데 최상위 Makefile.am 처럼 지정된 변수가 있고 이를 configure.ac 에서 치환해 준다면 해당 유효값이 들어가서 Makefile 이 만들어 지게 된다.(실제로는 Makefile.am 은 automake 를 통해 Makefile.in 로 만들어지고 configure 시 이를 입력값으로 취해서 Makefile 이 만들어 진다.)

7.6. 실행순서

위의 과정을 실행시키는 방법은 아래와 같다.

 aclocal
 autoheader
 autoconf
 automake --add-missing -copy
 ./configure
 make
 make check
 make install

흔히 configure 전까지의 과정을 묶어서 bootstrap 또는 autogen.sh 라는 script 로 만들어서 한꺼번에 실행시킨다. end user 는 단지 ./configre, make, make install 만을 하면 특정 소스를 build 할 수 있는데 autogen.sh 를 end user 가 할수있어야 한다 없어야 한다는데에는 여러 의견이 있다.

7.7. 요약과 전체 흐름 정리

지금까지 예제를 보면 최상위 Makefile.am 에 configure 시에 build 될 subdirectory 를 정하도록 하였으며 이 값을 알아내기 위해 configure.ac 에서 현 시스템을 검사하고 이 값을 넘겨주도록 되어있다. 즉 configure 실행후 make 를 하게 되면 최상위 Makefile 에 의해서 지정된 directory 만 build 가 이루어져 platform 에 따라 알맞는 소스가 build 되고 install 될 수 있다.

지금은 directory 단위로 특정 directory 를 build 할지 안할지를 결정하였지만 autotools 을 좀더 미시적은 범위에서 이용한다면 하나의 코드에 대해서도 define 문을 이용해서 선별적으로 코드가 build 되게 할 수 있다.