Using Autotools

In the first chapter, we have not really used the Autotools. It is not need to compile a project from the sources. But all files in the build process are not written by hand but generated from templates using Autotools.

Autotools is composed of several tools: aclocal, autoconf, automake and other that we will not see here, belonging to two packages: Automake and Autoconf.

  • Autoconf is used to generate the configure script, from a template named configure.ac. The configure script will check all characteristics of the host system and generate the makefiles from Makefile.in templates.
  • Automake is used to generate complete Makefile.in templates, following GNU standards from very simple Makefile.am templates.
Figure 3-1Autotools process

Now let's see a minimal example to start grasping the relationships between the various files.

3.1.1. Write sources

  1. Create an empty directory called tut_prog and enter in it.
  2. In this new directory, create a new file named main.c containing:
Example 3-1main.c:
#include <stdio.h> 
	
int main()
{
	printf("Hello world!\n");
	return 0;
}

3.1.2. Run Autoconf

  1. Write the following in a file named configure.ac:
Example 3-2minimal configure.ac:
AC_INIT([Tutorial Program], 1.0)
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES(Makefile)
AC_OUTPUT

The configure template script could be named configure.in. It is the name used in older version (before 2001) of Autoconf. Nevertheless, it is recommended to use configure.ac because the .in extension is already used by files processed by configure and generated by Automake: Makefile.in and autoheader: config.h.in.

AC_INIT, AM_INIT_AUTOMAKE, etc... are M4 macros. M4 is a macro expanding software used by Autotools; we don't need to know about it. When Autoconf will process this configure.in, the macros will be expanded and we will get a fresh huge configure script.

AC_INIT

Is the first mandatory macro. We need to indicate the name of the project and its version.

AM_INIT_AUTOMAKE

Initialize environment for Automake. It is needed in all projects using Automake.

AC_PROG_CC

Determine the C compiler to use.

AC_CONFIG_FILES

Create each file by copying the corresponding template file (with .in extension) and substituting the output variable values.

AC_OUTPUT

Marks the end of the configure template.

The use of some macros has changed between different versions of Autoconf:

  • The package name and version was defined as arguments of AM_INIT_AUTOMAKE instead of AC_INIT.
  • AC_OUTPUT was getting the list of generated files instead of using the additional macro AC_CONFIG_FILES.

Autoconf only knows its own macros but read additional ones in a file named aclocal.m4. These macros are used to extend Autoconf, it includes Automake macro (starting with AM_) and other third party macros. For instance, if you develop a library called foo, you might want to write an AC_CHECK_FOR_FOO macro so that developers using your library can check for its presence using Autoconf.

aclocal scans configure.ac and create an aclocal.m4 file which contains the macros mentioned in configure.ac. aclocal is part of the Automake package and search by default in Automake macros and in a system path typically /usr/share/aclocal.

  1. Launch aclocal. It will create a new file named aclocal.m4 in the current directory.
  2. Launch autoconf. It will create the configure script configure.

On my system, I actually get an extra directory called autom4te.cache. That is for Autoconf internal purposes. You do not need to care about it.

3.1.3. Run Automake

  1. Write the following in a file named Makefile.am:
Example 3-3minimal Makefile.am:
bin_PROGRAMS = tut_prog			
tut_prog_SOURCES = main.c

In Makefile.am are the very essential data needed to build the project: the target program, called tut_prog, will be put in a $prefix/bin/ directory; to build it we need main.c. Note that we don't specify how that will be built: Automake will figure it out. We haven't even mentioned the compiler in this pre-makefile.

Makefile.am will be processed by Automake; the result will be a Makefile.in. This Makefile.in is close to being a real makefile, but it contains variable names which will be replaced when the configure script will run, resulting in a real makefile (called Makefile). For instance, configure will write in the final Makefile what compiler to use (it is the compiler it found using the AC_PROG_CC macro).

  1. Run the command automake --add-missing --foreign. It will create a new file named Makefile.in as expected. Moreover, due to the switch --add-missing you get a few links to scripts necessary for building the project: depcomp, install.sh and missing. The other option --foreign tells to Automake that you don't want to follow GNU standard and you don't need mandatory documentation files: INSTALL, NEWS, README, AUTHORS, ChangeLog and COPYING. I have used it here to keep the number of created file to a minimum but else it is a good idea to provide these files, you can start with empty files.

3.1.4. Build project

  1. Run now the new configure script: ./configure. You get the following output and it create the makefile for your program.

    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 for gcc... gcc
    checking for C compiler default output file name... a.out
    checking whether the C compiler works... yes
    checking whether we are cross compiling... no
    checking for suffix of executables... 
    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
    configure: creating ./config.status
    config.status: creating Makefile
    config.status: executing depfiles commands
  2. Run now make, to build your program. You get the following output and a new tut_prog executable

    gcc -DPACKAGE_NAME=\"Tutorial\ Program\" -DPACKAGE_TARNAME=\"tutorial-program\"   \
            -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"Tutorial\ Program\ 1.0\"     \
            -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"tutorial-program\" -DVERSION=\"1.0\" \
            -I.     -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
    main.c: In function ‘main’:
    main.c:5: warning: return type of ‘main’ is not ‘int’
    mv -f .deps/main.Tpo .deps/main.Po
    gcc  -g -O2   -o tut_prog main.o
  3. Now, if you can write in /usr/local/bin, run make install to install your program. Else you need to log as root before or use sudo and run sudo make install. You should get.

    make[1]: Entering directory `/home/seb/Projects/Tutorial'
    test -z "/usr/local/bin" || /bin/mkdir -p "/usr/local/bin"
      /usr/bin/install -c 'tut_prog' '/usr/local/bin/tut_prog'
    make[1]: Nothing to be done for `install-data-am'.
    make[1]: Leaving directory `/home/seb/Projects/Tutorial'

    Then, if /user/local/bin is in your path, you can run your program from everywhere.

3.1.5. Clean project

  1. The program is installed, so you can clean the build directory running make clean. It removes all object files and the program but not the makefiles.

    test -z "tut_prog" || rm -f tut_prog
    rm -f *.o

    You can still run the program installed in /user/local/bin.

  2. To remove the installed program, run make uninstall. Like for the installation, you need to use have the writing right in the directory or use su or sudo.

    rm -f '/usr/local/bin/tut_prog'

3.1.6. Generate project

Running aclocal, automake and autoconf one by one is fine for a tutorial to understand exactly what's happen. But, for a real work, it's a bit tedious especially because there are other tools those could be needed like autoheader, autopoint or libtoolize. After creating the project, the makefiles generated by configure should take care of regenerating configure and all Makefile.in. Anyway, this lets a room for improvement and there are even two responses to this:

autoreconf

It is another tool part of the Autoconf package which is running all scripts in the right order. To start a new project, you can just run autoreconf --install and it will call all necessary commands.

autogen.sh

It is a script not part of Autotools, that it doing the same thing. There is one named gnome-autogen.sh which comes with GNOME common development package but other project can write their own ones.