For most software projects that go past the trivial state a build environment can assist in helping with finding dependencies, providing alternatives, documentation creation, unit testing, etc. One of the most flexible environments are provided by the GNU Autotools, but setting up a new Autotools project can be a bit cumbersome. It always seem to give me the feeling that I have to rediscover everything about the GNU Autotools and to avoid making the same mistakes over and over again I kept a lot of notes. The disadvantage of personal notes are of course:

  • They get disorganized
  • They are hard to keep up-to-date
  • They are not always available
  • It is difficult to transfer the knowledge contained in them to another person

So therefore I decided to do what I always do to solve these issues: I publish the knowledge on a subject that I obtained so far on my homepage. It will be series of instalments, each building on the knowledge from the previous instalments. In this first instalment a trivial ‘Hello, World!’ project will be created. Later instalments will provide information on:

But more subjects might be added in the future. It is also most likely that new insights will be added to already published parts and I will try to indicate the new additions as good as possible.

Since I consider these my personal notes they are not a replacement for the full GNU Autotools documentation and other resources. For more in-depth information the following on- and off-line resources are recommended:

Although I consider these my notes, complete with rough-edges and warts and all, and by no means a complete tutorial on the subject I do still appreciate any remarks or comments. Nowhere will a setup guide for the used tools be given. These differ to much from system to system and with the use of Google resources with better information than I can provide should be available.

Setup project structure

Go to the directory where you want to store your project, create the project directory and change your current working directory to the newly created one:

cd ~/projects; mkdir foobar; cd !$

Create the source-directory and create the main.cpp (or .c) file there:

mkdir src; cd src; touch main.cpp; cd ..

Create the directories to hold the M4 macros:

mkdir m4

Create initial files

These files act as placeholders for later development. However by creating them the Autotools tool-chain can be gradually created and tested.

The explanation of the entries are added as comments to the files themselves and are marked as such with ‘NH:’ on each line. This provides the possibility to just remove these comments without removing other possibly more useful comments.

Once entries are commented with ‘NH:’ in a file they will not be commented again in following similar files. So if you miss an explaining comment then please search for it in the sections previous to the one you are reading.

Create src/main.cpp

Create a ‘main.cpp’ file in the ‘src’-directory with the following contents:

// This is just the normal standard ‘Hello, World!’ source code.
#include <iostream>
 
int main()
{
    std::cout << "Hello, World!" << std::endl;
 
    return 0;
}

Create configure.ac

In the project’s root-directory create a ‘configure.ac’ file with the following contents:

dnl NH: Make sure that a specific minimum version of Autoconf is available
AC_PREREQ([2.67])
 
dnl NH: Initialize Autoconf. Specify the package's name, version
dnl NH: and whom to contact for bug-reports
AC_INIT([foobar], [1.0.0], [foobar@heirbaut.nl])
 
dnl NH: Define the place where to find the auxiliary build files like
dnl NH: install-sh, config.sub, config.guess etc.
dnl NH: I do not like them cluttering up my root directory, so I
dnl NH: put them in a directory named 'config'
AC_CONFIG_AUX_DIR([config])
 
dnl NH: Initialize Automake. The given options will be passed to
dnl NH: Automake:
dnl NH:   -Wall: Turn on all warnings
dnl NH:   -Werror: Treat Automake warnings as errors
dnl NH:   -Woverride: Warn on user redefinitions of Automake rules
dnl NH:                              or variables
dnl NH:   foreign: Do not build a GNU-standards compliant package. A
dnl NH:                        GNU package would require more files and setup.
AM_INIT_AUTOMAKE([-Wall -Werror -Woverride foreign])
 
dnl NH: Define a unique source file that is always available. This
dnl NH: macro expands to a sanity check to ensure the for example
dnl NH: not the wrong directory is given with the --srcdir option
AC_CONFIG_SRCDIR([src/main.cpp])
 
dnl NH: Let the system know where the local M4 macros are located.
AC_CONFIG_MACRO_DIR([m4])
 
# Checks for programs.
dnl NH: Find the correct compiler
AC_PROG_CXX
 
# Checks for libraries.
 
# Checks for header files.
 
# Checks for typedefs, structures, and compiler characteristics.
 
# Checks for library functions.
 
# Miscellaneous
dnl NH: Make known to the Makefiles where the config dir is.
AC_SUBST(ac_aux_dir)
 
dnl NH: Define the files to generate
AC_CONFIG_FILES([
    Makefile
    src/Makefile])
 
dnl NH: Generate the defined files.
AC_OUTPUT

Create Makefile.am

In the project-root create a ‘Makefile.am’ with the following contents:

# NH: Notify aclocal to scan for the m4 directory for M4 files.
ACLOCAL_AMFLAGS = -I m4
 
# NH: Indicate in which directories relative to this one other
# NH: Makefile.am files are to be found.
SUBDIRS = src
 
# NH: All files added to this one will also be deleted when the
# NH: 'maintainer-clean' target is specified with 'make'. If not
# NH: specified here not all files created by the toolchain will
# NH: be deleted.
MAINTAINERCLEANFILES = \
    aclocal.m4 \
    configure \
    Makefile.in
 
# NH: 'maintainer-clean-local' is a standard target within Autotools
# NH: that can be used as a hook to trigger further actions when the
# NH: 'maintainer-clean' target is called. In this case it makes sure
# NH: that directory specified by 'AC_CONFIG_AUX_DIR' in configure.ac
# NH: is deleted.
maintainer-clean-local:
	-rm -rf $(ac_aux_dir)
 
# NH: A personal target that I use to edit all project files at once
# NH: using my favorite editor.
edit:
	find . \
		-name '*.h' -o \
		-name '*.c' -o \
		-name '*.cpp' -o \
		-name Makefile.am -o \
		-name configure.ac | \
	xargs gvim

Create src/Makefile.am

In the project’s ‘src’-directory create a ‘Makefile.am’:

# NH: Define the program to be build
bin_PROGRAMS = foobar
 
# NH: Define the sources that make up the program
foobar_SOURCES = main.cpp
 
# NH: Set the compile flags
foobar_CFLAGS  = -Wall -Werror -pedantic -Wextra
 
MAINTAINERCLEANFILES = Makefile.in

Bootstrap and test the current setup

All initial files need to be given to the various tool-chain applications (aclocal, autoconf and automake), to generate the ‘configure’ script. This script will create ‘config.h’ and the ‘Makefile’s’. Here is how:

autoreconf -ivf

Now the application can be build:

./configure && make

And tested:

src/foobar

This finishes this first instalment. Have fun experimenting! For the next instalment on creating and using libraries with Autotools, see here.

Updates

2010-12-26

Added the macro ‘AC_CONFIG_MACRO_DIR’ to ‘configure.ac.

2014-01-14

  • Fixed some spelling mistakes.
  • Added a links to the next instalment.
  • Changed the comment prefix to ‘dnl’ instead of ‘#’ as it should be in a M4-based file as configure.ac.
  • Applied C++ instead of plain C for the source files.