The GNU autotools programs (autoconf, automake and libtool), which are used for making software portable between Unix-like operating systems, have been around for more than fifteen years now, but their use is still regarded by many programmers to be a dark art. It's fair to say that they aren't the most straightforward tools to become accustomed to, and their awkwardness has spawned the creation of at least one
competing build system.
Nevertheless, as far as open-source software goes, autoconf and automake are still the main game in town, and for anyone who wants to hack around in this area, becoming familiar with these tools is essential.
This series of tutorials is designed to provide an introduction to these tools by way of simple examples.
We'll start off with a very simple Hello World program, in plain C:
#include <stdio.h>
int main(int argc,char **argv) {
printf("Hello world\n");
}
Create a directory called
hello and within that, a subdirectory called
src:
mkdir -p hello/src
The topmost directory,
hello will contain the entire package, and
src will be where we place the source code. So now, take the snippet of c-code above, and save it in the file
hello/src/hello.c.
automake uses templates with the name
Makefile.am to build
Makefile.in templates for
autoconf to process. You will need to create a
Makefile.am file within every directory in your package that automake will perform its work in. So, for this example, create the following files.
hello/src/Makefile.am:
bin_PROGRAMS = hello
hello_SOURCES = hello.c
Some explanation is required here. Automake rules take the form of
target_
primary. So, above, where we have the rule
bin_PROGRAMS, we are specifying the list of programs that we are building that will be played in the
bin directory, when installed. Similarly, we could have used
sbin_PROGRAMS for any programs that we were building that we wish to place in the
sbin directory.
The
PROGRAMS primary will then look for source files from which it can be built. Since our target program is called
hello, we specify a list of sources (separated by spaces; in the above example, we only have the one source file,
hello.c) using the target
hello_SOURCES.
hello/Makefile.am:
SUBDIRS = src
SUBDIRS is a special variable that lists all of the subdirectories that
automake must process. If you were to have any subdirectories underneath
hello/src, then you'd also include a
SUBDIRS line in your
hello/src/Makefile.am file, listing each of them.
Now, create
hello/configure.ac with the following contents:
AC_INIT([hello],[0.0.1])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_OUTPUT([
Makefile
src/Makefile
])
configure.ac is
autoconf's primary configuration file, which uses the M4 macro processing language. We'll start looking at each of these directives from the top.
AC_INIT must always be the first directive called; here, we've used two arguments - the name of the package (in this case hello), and the version number (0.0.1).
AM_INIT_AUTOMAKE is used only when you're using
automake with
autoconf; it takes one argument (options to run automake with), but in this case we haven't supplied any. If we wanted to cause all warnings to make it abort, we could have put: AM_INIT_AUTOMAKE([-Werror]).
AC_PROG_CC is a macro that tells configure to look for a C compiler. When run, it will first look at the contents of the CC environment variable, and if this is empty, it will test for the presence of
gcc and then fall back to
cc if necessary. Should you wish autoconf to test for the presence of a C++ compiler, use
AC_PROG_CXX.
The final statement,
AC_OUTPUT lists the files that the configure script should create when it is run; in this case, two Makefiles, one in each directory. This should always be the last directive in the
configure.ac file.
Now, from within the
hello directory, run the following:
aclocal
touch NEWS README AUTHORS ChangeLog
automake --add-missing
autoconf
aclocal should be run every time you update
configure.ac; it will update the aclocal.m4 file, which provides the macros needed to build your configure script.
automake will process the
Makefile.am files, and build
Makefile.in files from them, for
autoconf to use. We give it the
--add-missing so that it will generate a number of files that it requires to be present (
COPYING,
INSTALL, and the shell scripts
install-sh and
missing). It also requires the files
NEWS,
README,
AUTHORS and
ChangeLog, but it cannot create these itself, so we touch them to create empty files; feel free to enter your own information into them.
Running
autoconf will build
Makefile.in files from the
Makefile.am files, and will create a
configure script. You'll be familiar with this script from the many free software packages that use autotools.
At this point, the program is ready for compilation:
./configure
make
make install
The configure script can be given a number of options, and you can see many of these by running it with
--help. One very common option is
--prefix, which tells configure that you want it installed somewhere other than the default location (
/usr/local):
./configure --prefix=/opt/hello
If you'd like to make a tarball for distribution, you can run:
make dist
...and you'll be left with the file
hello-0.0.1.tar.gz in the top-level directory, which will contain all the source code and autotools scripts needed to compile up the program independently of your main directory.
There are also other packaging options available;
make dist-zip will use
zip to create an archive;
make dist-shar will create a shell archive (ie, the entire distribution in one shellscript);
make dist-bzip2 will make a bzip2 tarball and
make dist-tarZ will use the old Unix compress command to compress the tar file.
So, we're now at the end of this first lesson. For further practice with GNU autotools, try writing a more complex program that requires several source files. Try copying the hello-0.1.tar.gz archive to a completely different Unix platform and compile it up there. Also, investigate some of the options that the
configure script provides.
In the next lesson, we'll look at some more complicated
Makefile.am files, and see how we can handle C header files within our source tree.
Errata
Note that an earlier version of this tutorial used a deprecated syntax for AC_INIT and AM_INIT_AUTOMAKE. I have now corrected this. Thanks to Alexandre Duret-Lutz for pointing this out, below
This story has been submitted to fsdaily.com! If you think this story should be read by the free software community, come vote it up and discuss it here: http://www.fsdaily.com/HighEnd/GNU_autotools_primer_part_one
Tracked: May 30, 16:07