본문 바로가기

컴퓨터/Linux

GNU Autotools 를 사용하여 Build 하기








1. GNU Autotools 소개


SW 를 개발하는데 있어 Source 를 편집하여 결과적으로 Executable Binary를 만들어야 하는데

작은 프로젝트의 경우 단순히 gcc 명령어를 통해 진행할 수 있지만 프로젝트가 커지다 보면 복잡도가 증가하여

사람 손으로 일일히 진행하기 어려워 진다.

이를 위해서 Build System 들이 생겨나게 되었고 그 중 하나인 GNU Autotools를 소개하고자 한다.


GNU Autotools 와 CMake가 가장 유명하다.




2. Autotools 구성



[Autotools 진행도]

출처 : Wiki-GNU_Build_System






3. Autotools 사용법


3-1. 프로젝트 생성 및 Makefile.am 생성


Project Folder 생성과 hello.cpp Makefile.am을 생성한다.


1
2
3
4
dev@dev:~/work$ tree ./helloworld/
./helloworld/
├── main.cpp
└── Makefile.am
cs


각 파일의 내용은 아래와 같다.


main.cpp

1
2
3
4
5
6
7
#include <iostream>
 
int main()
{
    std::cout << "Hello World!" << std::endl;
    return 0;
}
cs


Makefile.am

1
2
3
bin_PROGRAMS = hello
 
hello_SOURCES = main.cpp
cs





3-2. autoscan


hello.cpp와 Makefile.am 이 있는 동일 Path 내에서 autoscan을 실행한다.

그러면 autoscan.log와 configure.scan 이라는 파일이 자동으로 생성된다.


1
2
3
4
5
6
7
8
9
dev@dev:~/work/helloworld$ autoscan
dev@dev:~/work/helloworld$ tree
.
├── autoscan.log
├── configure.scan
├── main.cpp
└── Makefile.am
 
0 directories, 4 files
cs


autoscan에 의해서 configure.scan 파일이 나왔으며 이를 configure.ac 로 rename 한다.





3-3. configure.ac 수정


configure.ac 를 열면 아래와 같이 나온다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#                                               -*- 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([main.cpp])
AC_CONFIG_HEADERS([config.h])
 
# Checks for programs.
AC_PROG_CXX
 
# Checks for libraries.
 
# Checks for header files.
 
# Checks for typedefs, structures, and compiler characteristics.
 
# Checks for library functions.
 
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
cs


AC_INIT의 1번째 인자는 프로젝트 이름, 1번째는 버전 정보를 채워 넣는다. (3번째는 Bug Report를 받을 E-Mail 주소)


추가로 아래와 같이 AM_INIT_AUTOMAKE, AC_PROG_CC 를 추가해 준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
 
AC_PREREQ([2.69])
AC_INIT([hello], [1.0], [foo@foo.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([main.cpp])
AC_CONFIG_HEADERS([config.h])
 
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
 
# Checks for libraries.
 
# Checks for header files.
 
# Checks for typedefs, structures, and compiler characteristics.
 
# Checks for library functions.
 
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
cs





3-4. aclocal, autoheader, autoconf 실행


aclocal, autoheader, autoconf 커맨드를 실행하면 아래와 같이 프로젝트 내 파일이 늘어난다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
dev@dev:~/work/helloworld$ aclocal
dev@dev:~/work/helloworld$ autoheader
dev@dev:~/work/helloworld$ autoconf
dev@dev:~/work/helloworld$ tree
.
├── aclocal.m4
├── autom4te.cache
│   ├── output.0
│   ├── output.1
│   ├── requests
│   ├── traces.0
│   └── traces.1
├── autoscan.log
├── config.h.in
├── configure
├── configure.ac
├── main.cpp
└── Makefile.am
 
1 directory, 12 files
 
cs






3-5. automake 실행


아래와 같이 automake를 실행하여 Makefile.in 파일이 생성된다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
dev@dev:~/work/helloworld$ tree
.
├── aclocal.m4
├── autom4te.cache
│   ├── output.0
│   ├── output.1
│   ├── requests
│   ├── traces.0
│   └── traces.1
├── autoscan.log
├── compile
├── config.h.in
├── configure
├── configure.ac
├── depcomp
├── main.cpp
├── install-sh
├── Makefile.am
├── Makefile.in
└── missing
 
1 directory, 17 files
cs





3-6. configure and make


Build 하기 위한 사전작업은 전부 진행되었으며

이제 마지막으로 본격적인 Build를 위한 작업을 하면 된다.

configure 및 make를 하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
dev@dev:~/work/helloworld$ ./configure 
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking for g++... g++
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking dependency style of g++... gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
dev@dev:~/work/helloworld$ make
(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /home/dev/work/helloworld/missing autoheader)
rm -f stamp-h1
touch config.h.in
cd . && /bin/bash ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-am
make[1]: Entering directory '/home/dev/work/helloworld'
g++ -DHAVE_CONFIG_H -I.     --O2 -MT main.o -MD -MP -MF .deps/main.Tpo --o main.o main.cpp
mv -f .deps/main.Tpo .deps/main.Po
g++  --O2   -o hello main.o  
make[1]: Leaving directory '/home/dev/work/helloworld'
 
cs





3-7. 결과


Output으로 나온 hello 라는 Executable Binary를 실행하면 아래와 같이 나온다.


1
2
dev@dev:~/work/helloworld$ ./hello 
Hello World!
cs