Fun to Program – Build system

Date: 2013/08/15 (initial publish), 2021/08/02 (last update)

Previous Post Top Next Post


This was originally written and created around 2013 and may require to be updated. (2021)

Build system

There are many cross-platform build systems:

Please note there are many programs which come with the plain GNU Make as the build system . The plain GNU Make is simple and works fairly well across all modern Unix-like systems.


This is the most versatile and robust build system.

The internal of Autotools are beyond my taste for learning. (Yack! What a convoluted use of GNU m4 for such complicated tasks.)

But compared to other newer build systems, I would rather use Autotools. This is because: “better the devil you know than the devil you don’t know.”

As a user

The source package generated by the Autotools (= Autoconf + Automake + …) requires only basic tools available on any Debian systems:

As a user, you only deal with files such as configure and generated by the Autotools. There is no need for any specialized external tools such as GNU M4 nor Perl nor Autotools.

They can be build as follows:

$ ./configure
$ make
$ sudo make install

The schematic relationship can be visualized as:

program.c --------------------------------------\
program.h --------------------------------------+--[make]--> program --\                 /--> config.h --/    / --+--[./configure]--+--> Makefile ------+

TIP: The above build process is true not just for source packages generated by the Autotools but for many other source packages.

Here, the template files such as and have embedded strings such as @CC@ and @prefix@ and they are replaced by the name of the particular C compiler and the installation directory using the Sed program executed from the configure script. It is good idea not to mess with these directly to customize your package build process.

Instead, you have 2 basic ways to customize your package build process as a user.

As for the configure options, you get their good explanation as follows:

$ ./configure -h

You should check all available command line options displayed. This is because the configure script is meant to be run non-interactively.

As for the make command, since the Makefile generated by the Autotools follows GNU coding standards, please read “Makefile Conventions” in the GNU coding standards to learn how to change behavior of make.

TIP: The default installation destination is /usr/local.

As an upstream

Autotools (= Autoconf + Automake + …) is a tool to create the portable source package with minimal efforts. It is not easy to make portable across different platforms. It generates a good set of configure, and required for a source package from simple data in the and files using the autoreconf -i command which runs all the Autotools in the right sequences.

program.h--------------+ --+       |           +--> configure----------V
               +--[autoreconf -i]--+--> --[./configure]--> config.h  --+                   +--> --[./configure]--> Makefile

Suppose you have hello.c.

#include <stdlib.h>
#include <stdio.h>
#include "config.h"
    printf("Hello, world! version: %s\n", VERSION);
    return EXIT_SUCCESS;

Then run autoscan to generate initial template of and edit it manually to the shape.

$ autoscan warning: missing AC_CHECK_HEADERS([stdlib.h]) wanted by: hello.c:1
$ mv configure.scan
$ vim

Since strict GNU compliance is not easy, lets make this as a “foreign” package to avoid complication:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT([hello], [0.1], [])

# Manually added

# Checks for programs.

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT defines programs to be built and relationship of source files in very simple way as.

bin_PROGRAMS = hello
hello_SOURCES = hello.c


$ ls

Let’s generate configure, and using autoreconf -i -v -f (-f option is needed only when you are running this command second time. -v is for verbose output.):

$ autoreconf -i -v -f
autoreconf: Entering directory `.'
autoreconf: not using Gettext
autoreconf: running: aclocal --force
autoreconf: tracing
autoreconf: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
autoreconf: running: /usr/bin/autoheader --force
autoreconf: running: automake --add-missing --copy --force-missing installing './install-sh' installing './missing' installing './depcomp'
autoreconf: Leaving directory `.'

Let’s make ./configure to change the binary program destination from /usr/local/bin to /usr/bin and to change the entire install destination from / to ./tmp for use by the binary distribution package build. Then let’s run it from ./tmp/usr/bin/hello.

$ ./configure --prefix=/usr
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... gawk
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 for style of include used by make... GNU
checking dependency style of gcc... 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
$ make
make[5]: Entering directory `/path/to/hello'
make  all-am
make[6]: Entering directory `/path/to/hello'
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o ...
mv -f .deps/hello.Tpo .deps/hello.Po
gcc  -g -O2   -o hello hello.o
make[6]: Leaving directory `/path/to/hello'
make[5]: Leaving directory `/path/to/hello'
$ DESTDIR=./debian/tmp make install
make[5]: Entering directory `/path/to/hello'
make[6]: Entering directory `/path/to/hello'
 /bin/mkdir -p './debian/tmp/usr/bin'
  /usr/bin/install -c hello './debian/tmp/usr/bin'
make[6]: Nothing to be done for `install-data-am'.
make[6]: Leaving directory `/path/to/hello'
make[5]: Leaving directory `/path/to/hello'
$ # now run it
$ ./debian/tmp/usr/bin/hello
Hello, world! version: 0.1

For more, Using GNU Autotools

TIP: If you find instead of in the source tree, the source is very old. It is good idea to update the configuration files to match newer versions of the Autotools.

TIP: You should commit only hand-edited files to the upstream VCS. For Autotools, these are,, */, AUTHORS, and NEWS(optional). Do not bother to track other generated files.

See :



Previous Post Top Next Post