Linux build tool - autotools

Autotools는 linux에서 가장 보편적으로 사용하는 빌드 도구 입니다.

configure.ac, Makefile.am, configure, Makefile.in, aclocal.m4 와 같은 폴더구조를 많이 보셨을 겁니다. 이런 구조로 만들어진 빌드 도구를 autotools라고 합니다.
Autotools는 automake 또는 autoconf와 헷갈릴 수 있는데, Autotools는 Autoconf, Automake, Libtool, Gettext로 구성되는 것을 Autotools라고 부릅니다.
Autotools의 최고 장점은 host, target, toolchain에 큰 의존성이 없이 빌드가 가능하다는 점 입니다.

아래와 같은 순서로 Autotools 환경을 구성할 수 있습니다.
1. Makefile.am
2. configure.ac
3. configure
4. make

아래 가이드는 github에 올려두었으니 참고하시기 바랍니다.
$ git clone https://github.com/juwith/simplest-autotools.git
$ git checkout 380e0d6d43db10cc6de5ec4dbaceb4337d5d2be4

Makefile.am
Makefile.am은 Makefile이 생성될 폴더 위치에 모두 생성합니다.
하나의 bin과 하나의 lib를 생성하는 프로젝트를 생성하는 경우를 예를 들어 봅시다.

.
├── Makefile.am
├── src
│   ├── hello.c
│   ├── hello.h
│   └── Makefile.am
└── test
    ├── main.c
    └── Makefile.am

src에 있는 소스는 동적 라이브러리르 생성할 소스고, test에 있는 소스는 바이너리를 생성할 소스 입니다.

Makefile.am에는 빌드 할 대상을 지정합니다. 최상위 폴더에 있는 Makefile.am은 빌드 대상이 하위 폴더이므로 아래와 같이 지정합니다.

Makefile.am
SUBDIRS = src test 

이 때 SUBDIRS 변수의 순서는 빌드 될 순서 입니다. test에서 생성 될 바이너리는 src에서 생성될 라이브러리를 사용할 예정이므로 src를 먼저 빌드합니다.

src/Makefile.am
lib_LTLIBRARIES = libhello.la

libhello_la_SOURCES = \
           hello.c

include_HEADERS = \
           hello.h

이 외에 참조할 cflags나 ldflags가 있다면 아래와 같이 추가합니다.
libhello_la_CFLAGS = \
-I$(top_srcdir)/include

libhello_la_LDFLAGS = \
-lpthread

test/Makefile.am
bin_PROGRAMS = hello

hello_SOURCES = main.c

hello_CFLAGS = \
           -I$(top_srcdir)/src

hello_LDADD = \
            $(top_builddir)/src/libhello.la



top_srcdir 매크로는 소스 최상위 폴더입니다.
top_builddir 매크로는 빌드폴더 최상위 폴더 입니다. autotools는 소스 폴더와 빌드 폴더를 다르게 지정할 수 있으며, 소스폴더와 빌드폴더가 다른 경우 lib~.la는 빌드폴더에 생성되기 때문에 라이브러리 참조를 위해서는 top_builddir변수를 사용합니다.

이제 빌드를 위한 Makefile.am 준비는 모두 끝났습니다.

configure.ac
Makefile.am이 있는 상태에서 아래 명령어를 입력합니다.
$ autoscan
autoscan 명령을 내리면 autoscan.log 파일이 생성됩니다.
configure.scan은 configure.ac로 이름을 바꿔 줍니다.
$ mv configure.scan configure.ac
.
├── autoscan.log
├── configure.scan
├── Makefile.am
├── src
   ├── hello.c
   ├── hello.h
   └── Makefile.am
└── test
    ├── main.c
    └── Makefile.am


자동 생성 된 configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/hello.h])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile
                 test/Makefile])
AC_OUTPUT

프로젝트 이름 변경을 위해 AC_INIT에 FULL-PACAKGE-NAME을 변경합니다.
AC_INIT([simplest-autotools], [VERSION], [BUG-REPORT-ADDRESS])

autoconf 폴더 지정을 위해 아래 매크로를 추가합니다.
AC_CONFIG_MACRO_DIR([m4])

automake init을 위해 아래 매크로를 추가합니다.
AM_INIT_AUTOMAKE

라이브러리 추가를 위해 아래 매크로를 추가합니다.
AM_PROG_AR
LT_INIT

수정 후 configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([simplest-autotools], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/hello.h])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

AM_INIT_AUTOMAKE

# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O

# Checks for libraries.
AM_PROG_AR
LT_INIT

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile
                 test/Makefile])
AC_OUTPUT

configure

autoconf 시 필요한 파일을 추가합니다.
$ touch INSTALL NEWS README AUTHORS ChangeLog

configure파일을 생성합니다.
$ autoreconf -vfi

Make
$ ./configure --prefix=/home/juwith/test
$ make
$ make install

결과
.
├── bin
   └── hello
├── include
   └── hello.h
└── lib
    ├── libhello.a
    ├── libhello.la
    ├── libhello.so -> libhello.so.0.0.0
    ├── libhello.so.0 -> libhello.so.0.0.0
    └── libhello.so.0.0.0


$ ./hello
hello lib

댓글