GNU autoconf, automake

오픈소스 프로그램들은 대부분 리눅스에서 아래처럼 컴파일할수 있습니다.

$ ./configure
$ make
$ sudo make install

configure 스크립트를 실행하여 시스템에 맞게 컴파일 되도록 Makefile을 생성해줍니다. 유닉스가 종류가 많고 다양하기 때문에 그 모두를 Makefile 하나로만 지원하기는 어렵습니다. autoconf와 automake를 이용하면, 자동으로 타켓 시스템을 분석해주고, Makefile을 자동으로 만들어줍니다. configure를 실행하면 Makefile과 config.h 파일이 생성되는데, config.h에 시스템에서 제공되는 기능에 대해서 매크로로 정의를 해줍니다. 소스 파일에서 config.h를 include하고 매크로에 따라 특정 기능이 지원 안되면 다른 방법으로 구현하여 프로그램의 이식성을 높일수 있습니다. autoconf와 automake를 쓰는것만으로 프로그램 자체의 이식성이 높아지지는 않습니다.

저는 주로 FreeBSD에서 ports를 사용하고, 개발도 Berkeley Parallel make를 이용하기 때문에 autoconf와 automake를 배울 필요를 못느꼈었습니다. 사실 cross platform이 중요하지 않고 소스의 구조가 복잡하지 않으면 make의 기본 기능으로도 큰 불편없이 개발할수 있습니다. 요즘 빌드 시간도 짧으니 dependency도 크게 신경안쓰고 항상 make clean;make 해도 개발 자체가 크게 느려지지는 않더군요. 제가 유닉스에서 개발하는 프로그램은 대부분 5000 라인 이하의 데몬 프로그램들입니다. 거의 C에 가까운 C++ 프로그램이죠.

요즘 AMD64 서버들에 리눅스를 깔고 서버 프로그램들을 리눅스와 프비에서 동시에 지원하기 위해서 작업을 하고 있습니다. 처음에는 Makefile.linux를 따로 만들었는데 Makefile을 따로 관리하기 보다는 autoconf와 automake를 이용하면 더 편할것 같아서, autoconf, automake를 적용해보고 있습니다.

configure 스크립트가 만들어지기 까지 여러가지 명령을 순서대로 실행해야 해서 처음에는 복잡하게 느껴지지만 조금 익숙해지면 어렵지 않습니다. 사용자가 직접 만들어줘야하는 파일은 Makefile.amconfigure.ac 두개입니다. 나머지는 부수적인 파일들로 autoconf, automake 동작에 큰 영향을 주지 않습니다. (AUTHORS, README, COPYING 등)

libevent를 이용한 echo server를 C++로 예제 프로젝트로 만들어봤습니다.

Makefile.am에서는 실행파일과 실행파일을 만들기 위한 소스를 지정해줍니다. 아주 간단합니다.

bin_PROGRAMS = echo_server
echo_server_SOURCES = echo_server.cpp

configure.ac는 조금 복잡합니다. 프로그램 이름, 버전, 이메일 등을 적어주고 사용하는 라이브러리에 대해서 기술하도록 되어있습니다. libevent에 관련한 내용(파란색)이 대부분인데 이 부분은 memcached 에 포함된 configure.ac 파일을 참고했습니다.

AC_INIT(echo_server_libevent, 1.0, mix1009@gmail.com)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
AM_CONFIG_HEADER(config.h)

AC_PROG_CXX
AC_PROG_INSTALL

AC_ARG_WITH(libevent,
   AC_HELP_STRING([–with-libevent=DIRECTORY],[base directory for libevent]))
if test “$with_libevent” != “no”; then
   CFLAGS=”$CFLAGS -I$with_libevent/include”
   CXXFLAGS=”$CXXFLAGS -I$with_libevent/include”
   LDFLAGS=”$LDFLAGS -L$with_libevent/lib”
fi

LIBEVENT_URL=http://www.monkey.org/~provos/libevent/
AC_CHECK_LIB(event, event_set, ,
   [AC_MSG_ERROR(libevent is required.  You can get it from $LIBEVENT_URL)])

AC_CONFIG_FILES(Makefile)
AC_OUTPUT

이 외에도 부수적으로 준비해야하는 파일들이 몇개있습니다. NEWS, README, AUTHORS, ChangeLog는 필수적으로 있어야하는 파일들이고, 몇가지는 automake를 실행할때 –add-missing을 인자로 주면 자동으로 만들어줍니다.

제가 사용하는 FreeBSD 6.2 기준으로 설명드리겠습니다. autoconf, automake 여러버전이 설치될수 있는데, 제가 사용한 버전은 아래와 같습니다.

/home/mix1009> pkg_info | grep auto
autoconf-2.59_2     Automatically configure source code on many Un*x platforms
automake-1.9.6      GNU Standards-compliant Makefile generator (1.9)

아래와 같이 실행하면 configure가 생성됩니다.

/home/mix1009/work/echo_server_libevent> ls -l
total 8
-rw-r–r–  1 mix1009  wheel    66 May  8 13:39 Makefile.am
-rw-r–r–  1 mix1009  wheel   650 May  8 13:39 configure.ac
-rw-r–r–  1 mix1009  wheel  3027 May  8 13:39 echo_server.cpp
/home/mix1009/work/echo_server_libevent> aclocal19
/home/mix1009/work/echo_server_libevent> autoheader259
/home/mix1009/work/echo_server_libevent> autoconf259
/home/mix1009/work/echo_server_libevent> touch README AUTHORS NEWS ChangeLog
/home/mix1009/work/echo_server_libevent> automake19 –add-missing
configure.ac: installing `./install-sh’
configure.ac: installing `./missing’
Makefile.am: installing `./INSTALL’
Makefile.am: installing `./COPYING’
Makefile.am: installing `./depcomp’
/home/mix1009/work/echo_server_libevent> ls -l
total 210
-rw-r–r–  1 mix1009  wheel       0 May  8 13:40 AUTHORS
lrwxr-xr-x  1 mix1009  wheel      35 May  8 13:41 COPYING@ -> /usr/local/share/automake19/COPYING
-rw-r–r–  1 mix1009  wheel       0 May  8 13:40 ChangeLog
lrwxr-xr-x  1 mix1009  wheel      35 May  8 13:41 INSTALL@ -> /usr/local/share/automake19/INSTALL
-rw-r–r–  1 mix1009  wheel      66 May  8 13:39 Makefile.am
-rw-r–r–  1 mix1009  wheel   17475 May  8 13:41 Makefile.in
-rw-r–r–  1 mix1009  wheel       0 May  8 13:40 NEWS
-rw-r–r–  1 mix1009  wheel       0 May  8 13:40 README
-rw-r–r–  1 mix1009  wheel   31538 May  8 13:40 aclocal.m4
drwxr-xr-x  2 mix1009  wheel     512 May  8 13:41 autom4te.cache/
-rw-r–r–  1 mix1009  wheel     640 May  8 13:40 config.h.in
-rwxr-xr-x  1 mix1009  wheel  150289 May  8 13:40 configure*
-rw-r–r–  1 mix1009  wheel     650 May  8 13:39 configure.ac
lrwxr-xr-x  1 mix1009  wheel      35 May  8 13:41 depcomp@ -> /usr/local/share/automake19/depcomp
-rw-r–r–  1 mix1009  wheel    3027 May  8 13:39 echo_server.cpp
lrwxr-xr-x  1 mix1009  wheel      38 May  8 13:41 install-sh@ -> /usr/local/share/automake19/install-sh
lrwxr-xr-x  1 mix1009  wheel      35 May  8 13:41 missing@ -> /usr/local/share/automake19/missing

처음 없는 파일들을 만들기 위한 명령인 touch와 automake 실행할때 –add-missing은 파일이 만들어진 이후로는 인자를 주지 않아도 됩니다. 파일이 모두 만들어진 이후로는 아래와같은 명령만 쳐주면 됩니다.

/home/mix1009/work/echo_server_libevent> aclocal19
/home/mix1009/work/echo_server_libevent> autoheader259
/home/mix1009/work/echo_server_libevent> autoconf259
/home/mix1009/work/echo_server_libevent> automake19


그리고 –add-missing으로 파일을 생성할때 심볼릭 링크로 생성되는데 소스를 배포하거나 CVS에 commit하기 전에, 파일을 직접 복사하는게 좋습니다.

configure 스크립트가 생성되면, 아래와 같이 타켓 시스템에서 컴파일할수 있습니다. configure가 만들어지기 전까지는 하나의 서버에서 실행해서 결과 파일들(configure, Makefile.in, config.h.in 등)을 배포하면 되지만, 이후 부분부터는 타켓 플렛폼에서 실행해야 합니다. configure가 실행될때 타켓 시스템에 특정 기능이 구현되었는지를 검사하고 라이브러리 설치여부등을 검사합니다. 그 결과에 따라서 config.h 파일을 만들어줍니다.

아래처럼 타겟 시스템에서 컴파일하고 설치할수 있습니다.

/home/mix1009/work/echo_server_libevent> ./configure –with-libevent=/usr/local
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
(생략)
checking for event_set in -levent… yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
/home/mix1009/work/echo_server_libevent> make
(생략)
/home/mix1009/work/echo_server_libevent> sudo make install
(생략)

리눅스에서는 configure를 인자없이 실행해도 libevent를 정상적으로 찾는데, FreeBSD에서는 위와 같이 인자로 지정해주어야 찾습니다.

각 툴들을 간략히 설명하겠습니다. aclocal은 autoconf에서 미처 구현되지 못한 부분(?)을 처리하는 것으로 차후에는autoconf에 포함될거라고 합니다. autoheaders는 configure.ac로부터 config.h.in을 만듭니다. automake는 configure.ac와 Makefile.am 내용에 따라서 Makefile.in을 생성합니다.autoconf는 configure.ac에 따라서 configure를 생성합니다. configure는 config.h.in과Makefile.in을 기준으로 시스템 정보를 분석하여 Makefile과 config.h를 만들어줍니다.

각 프로그램의 입출력 파일들을 살펴보면 아래와 같습니다. http://sourceware.org/autobook/의 Appendix C를 참고했습니다.

configure.ac — aclocal —> aclocal.m4
configure.ac, (optional aclocal.m4) — autoheaders —> config.h.in
configure.ac, Makefile.am — automake —> Makefile.in
configure.ac, (optional aclocal.m4) — autoconf —> configure
Makefile.in, config.h.in — configure —> Makefile, config.h

처음에는 복잡하게 느껴지지만, 한번 사용해보면 Makefile.am에서 소스 파일만 추가하고, 사용하는 라이브러리가 추가될때 configure.ac에서 라이브러리 지정만 하면 되기 때문에 사용에 어려움이 없습니다. 도입후에 여러 플렛폼에서 컴파일하면서 발생하는 문제점들을 하나씩 해결해 나가면 프로그램의 이식성을 높일수 있습니다. 문제가 발생하는 함수등을 configure.ac에서 지정하고 config.h에 정의된 매크로에 따라서 소스에서 적절히 처리하면 이식성이 차차 높아지게 됩니다.

autoconf, automake 실행하기 전 소스입니다. libevent를 이용한 echo 서버 예제 입니다. 소스 자체의 완성도는 높지 않습니다. configure.ac, Makefile.am, echo_server.cpp, COPYING 네개의 파일이 포함되어있습니다.

1214426580.tgz

2 thoughts on “GNU autoconf, automake

  1. 이용운

    ㅎㅎㅎ 안녕하세요. 이렇게 블로그에서 인사드리니 더 반갑네요. 🙂

    회사에서 하는 일에서 libevent를 써볼까 하다가, libevent에 관련된 글을 찾다보니, 눈에띄는 URL이 있어서 오게됐네요.

    잘지내고 계시죠? 🙂

    Reply
    1. mix1009

      잘 지내고 있지? 난 그럭저럭… 같은 일 계속 하다보니 좀 지겹기도 하네. 요즘 공부 너무 안해서 블로그라도 열심히 하면서 새로운걸 배우려고 노력중이다. 참 그리고 회사 다시 선릉으로 이사했다.

      Reply

Leave a Reply

Your email address will not be published.