GNU Automake By Example
Table of Contents
- Abstract
- A Minimal Project
- Editing Automake-based Projects with KDevelop
- Adding Doxygen Support
- A More Complex Example
- Topics Not Covered
- Links
Abstract
This article presents several simple Automake/Autoconf-based projects. I assume that you know what Automake, Autoconf, and configure
are, and that you know how to install a software package from sources (i.e., you know how to invoke "configure & make & make install"
). (If you don’t, you can still follow the instructions to create a very small project to play around with.) This article does not contain lengthy explanations or detailed background information. Rather, I present a few examples that (hopefully) get the ideas across.
Some of the topics for which examples are presented:
- Doxygen support
- Multiple subdirectories
- Flex/Bison support
- Libtool Convenience libraries
- KDevelop Automake Manager
I have tested all examples on GNU/Linux using Automake 1.9.5 and Autoconf 2.59.
I am not an Automake guru myself (not yet ). When I ported mfGraph to Automake, I was looking for short and simple examples like those presented in this article that would illustrate what the Automake and Autoconf manuals were talking about. I didn’t find exactly what I was looking for. The Automake Book [1], while being a good introduction, didn’t answer all my questions either. If you’re like me, maybe you’ll find this article helpful.
I appreciate all your feedback, especially if you find any errors or abuses of Automake/Autoconf concepts.
In the meantime, another very interesting book about Automake/Autoconf is available online: Autotools: a practitioner’s guide to Autoconf, Automake and Libtool [7] at the Free Software Magazine web site.
A Minimal Project
Create a directry structure with the following files in it:
foobar/
m4/
src/
Makefile.am
<your source code files>
AUTHORS
COPYING
ChangeLog
Makefile.am
NEWS
README
autogen.sh
configure.ac
This is the source tree of the project. Apart from the .cpp and .h files, these text files are the only files that you need to create for a minimal GNU Automake/Autoconf-based project. All other files will be generated by the tools.
Root Makefile.am
Let’s take a look at the contents of the files. The files named Makefile.am
are the input to the Automake tool. First, the root Makefile.am:
foobar/Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
EXTRA_DIST = autogen.sh
- For a minimal project, we only need to name the subdirectories containing additional
Makefile.am
files. - The option
-I m4
tells Autoconf to look for additional Autoconf macros in the m4 subdirectory. We’ll make use of this when we introduce Doxygen. - The
EXTRA_DIST
directive tells Automake to place the fileautogen.sh
in the distribution archive, so that that file is shipped to our users.
autogen.sh
The file autogen.sh
is a shell script that invokes autoreconf
for us. The tool autoreconf
is responsible for calling Autoconf, Automake and related tools in the right order.
Don’t forget to set the Execute bit for the file autogen.sh
!
foobar/autogen.sh:
#!/bin/sh
autoreconf --force --install -I config -I m4
- The
--force
option rebuilds theconfigure
script regardless of its timestamp in relation to that of the fileconfigure.ac
. - The option
--install
copies some missing files to the directory, including the text filesCOPYING
andINSTALL
. - We add
-I config
and-I m4
so that the tools find the files that we’re going to place in those subdirectories instead of in the project root.
Note: Don’t run autogen.sh
yet. We have to write configure.ac
and Makefile.am
first.
For more information on autoreconf
, run info autoreconf
. If you’re using KDE, you can also enter info:autoreconf
in the Konqueror address box.
configure.ac
The file configure.ac
is the input to Autoconf. Autoconf produces the configure
shell script, which, in turn, produces the final Makefiles, so that users can type make install
to install your software.
foobar/configure.ac:
dnl Process this file with autoconf to produce a configure script.
AC_INIT(foobar, 1.0, me@mail.com)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(src/foobar.cpp)
AM_INIT_AUTOMAKE
AC_PROG_CXX
AC_OUTPUT(Makefile src/Makefile)
- The lines up to and including
AM_INIT_AUTOMAKE
are more or less boilerplate code.AC_CONFIG_AUX_DIR
is the place where some helper files will be placed. This keeps the root directory cleaner. AC_PROG_CXX
enables C++ compiler support. Autoconf will generate code for theconfigure
script that determines the location of the compiler, tests various compiler switches, etc.- Larger projects will require additional checks and switches here.
AC_OUTPUT
lists the Makefiles that theconfigure
script should generate on the user’s machine. For everyMakefile.am
that we write, Automake will generate aMakefile.in
. Theconfigure
scripts turns these into Makefiles.
For more information on Autoconf, please see the Autoconf manual (info autoconf
).
src/Makefile.am
Each subdirectory has its own Makefile.am
. Our file src/Makefile.am
builds an executable program from a single C++ source file.
foobar/src/Makefile.am:
bin_PROGRAMS = foobar
foobar_SOURCES = foobar.cpp
"PROGRAMS"
is called a primary. Other primaries include:LIBRARIES
for static libraries (.a)LTLIBRARIES
for Libtool-based shared libraries (.la)HEADERS
- …
- The prefix
"bin_"
tells Automake where to copy the resulting program when the user runsmake install
. Known directory prefixes include:bin_
– for programs, e.g.,/usr/local/bin
lib_
– where libraries are placed, e.g.,/usr/local/lib
include_
– where header files are placed, e.g.,/usr/local/include
pkginclude_
– e.g.,/usr/local/include/foobar
noinst_
– files that will not be copied anywhere bymake install
- …
Note: The user can specify the locations of these directories when running the
configure
script. For more info, runconfigure --help
. "SOURCES"
is a variable that lists the source files of the program. For programs and libraries, possible variables include:CFLAGS, CPPFLAGS, CXXFLAGS
– extra arguments passed to the compiler/preprocessorLIBADD
– extra objects for a libraryLDADD
– extra objects for a programLDFLAGS
– extra arguments passed to the linker- …
For more information on Automake, please see the Automake manual (info automake
).
Running the Tools
Now it’s time to run the tools and attempt a build.
- Run
./autogen.sh
and see which files are produced by this step. - Create a separate build tree and run
configure:
> mkdir build > cd build > ../configure
Note: You can pass various arguments to
configure
. Take a look at these by runningconfigure --help
.Again, see which files are produced by this step.
- Run
make
, thenmake install.
- To produce a distribution package, run
make dist
or, better yet,make distcheck.
Editing Automake-based Projects with KDevelop
You can work with Automake-based projects from within the KDevelop IDE.
- Click Project > Import Existing Project…
- Specify the directory that contains your Automake-based project
(Screenshot taken in KDevelop 3.2.0) - Using the Automake Manager, you can add/remove sub-projects,
add/remove files, set options, etc.
- If your main program is not named after the project, you need
to set the Run Options in Project >
Options to be able to debug:
Note: Not everything can be done directly in
the IDE. Sometimes you will have to edit the files
configure.ac
and Makefile.am
manually.
Adding Doxygen Support
Doxygen is a tool that generates HTML documentation from special comments in C++ source code. (However, I assume you already know the tool. If you don’t, you can safely skip this section.)
Adding Doxygen support means that we want to have a Make target that generates the HTML documentation, and that the generated HTML documentation should be included in the distribution archive. For this to work, you need to download a few files from Oren Ben-Kiki’s web site and place them in your directory structure (new files are in boldface):
foobar/
m4/
ac_doxygen.m4
src/
Makefile.am
<your source code files>
AUTHORS
COPYING
ChangeLog
Makefile.am
NEWS
README
aminclude.am
autogen.sh
configure.ac
doxygen.cfg
Note: Older versions of these files seem to be available at the Autoconf Macro Archive, but these don’t work as good.
ac_doxygen.m4
contains Autoconf macros that we can use inconfigure.ac.
aminclude.am
contains the Doxygen-related make targets.doxygen.cfg
is aDoxyfile
template that contains a few macros that will be expanded when theconfigure
script is run. Modify the file so that it suits your needs (and the version of Doxygen that you’re using!).
Next, we need to make a change to the file Makefile.am
in the root directory so that the generated documentation will be included in the distribution archive (added lines are in boldface):
foobar/Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src
include aminclude.am
EXTRA_DIST = autogen.sh $(DX_CONFIG) doc/html
Finally, we add Doxygen-related macro calls to the file configure.ac
(added lines are in boldface):
foobar/configure.ac:
dnl Process this file with autoconf to produce a configure script.
AC_INIT(foobar, 1.0, me@mail.com)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(src/foobar.cpp)
AM_INIT_AUTOMAKE
AC_PROG_CXX
DX_HTML_FEATURE(ON)
DX_CHM_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
DX_MAN_FEATURE(OFF)
DX_RTF_FEATURE(OFF)
DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_INIT_DOXYGEN(foobar, doxygen.cfg, doc)
AC_OUTPUT(Makefile src/Makefile)
Documentation will be generated when you run make doxygen-doc
or when you produce a distribution archive with make distcheck
.
Note: When you look at the generated Makefile, you’ll see that the documentation only depends on the files in pkginclude_HEADERS
, regardless of what you set "INPUT"
to in the file doxygen.cfg
. If you want to force the documentation to be re-generated (maybe before the final build), it might be a good idea to delete the entire Doxygen output folder (doc/html
by default) before doing the build.
A More Complex Example
Finally, I’d like to present a more complex example with the following features:
- Several subdirectories, each with their own
Makefile.am
- Libtool shared and convenience libraries
- Generated source files (the typical Flex/Bison example)
The new directory structure looks like this (added entries in boldface):
foobar/
m4/
ac_doxygen.m4
some_shared_lib/
Makefile.am
<your some_shared_lib-specific source code files>
src/
Makefile.am
<your source code files>
AUTHORS
COPYING
ChangeLog
Makefile.am
NEWS
README
aminclude.am
autogen.sh
configure.ac
doxygen.cfg
For Libtool libraries as well as for Flex/Bison, we need additional checks in configure.ac
. Also, we must specify the new subdirectory (added text in boldface):
foobar/configure.ac:
dnl Process this file with autoconf to produce a configure script.
AC_INIT(foobar, 1.0, me@mail.com)
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR(src/foobar.cpp)
AM_INIT_AUTOMAKE
AC_PROG_CXX
AM_PROG_LEX
AC_PROG_YACC
AC_PROG_LIBTOOL
DX_HTML_FEATURE(ON)
DX_CHM_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
DX_MAN_FEATURE(OFF)
DX_RTF_FEATURE(OFF)
DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_INIT_DOXYGEN(foobar, doxygen.cfg, doc)
AC_OUTPUT(Makefile src/Makefile some_shared_lib/Makefile)
Note: When building with Libtool, all sources will be compiled twice–once for static libraries and once for dynamic libraries. If you only ever build dynamic libraries, you can save compilation time by inserting AC_DISABLE_STATIC
before AC_PROG_LIBTOOL
.
The additional subdirectory must also be added to Makefile.am
(added text in boldface):
foobar/Makefile.am:
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src some_shared_lib
include aminclude.am
EXTRA_DIST = autogen.sh $(DX_CONFIG) doc/html
In the file src/Makefile.am
, we build a Libtool convenience library from the sources in the src
directory. A convenience library is a library that is not installed (as specified by the "noinst_"
prefix). Such a library is useful whenever you want to link the same set of sources into several executables or shared libraries, without having to list these sources in every Makefile.am
.
Another complication in src/Makefile.am
is that it includes a Flex/Bison-generated parser. With Automake, you only have to list the Bison grammar file (.yy) and the Flex lexer file (.ll) file; Automake knows how to invoke Flex/Bison to generate the source code.
The only thing you have to remember is to specify mfg_bison.h
in BUILT_SOURCES
. This way, Automake will run the commands that generate mfg_bison.h
before compiling any other files that might depend on it. (Typically, the generated mfg_flex.cpp
is one such file that depends on mfg_bison.h
. If you don’t specify BUILT_SOURCES
, it might happen that the Make tool tries to compile mfg_flex.cpp
before mfg_bison.h
exists.)
We also specify public_api.h
in the list pkginclude_HEADERS
. When the user runs make install
, the listed files will be copied to /usr/local/include/foobar
(or a different directory passed to configure
).
foobar/src/Makefile.am:
BUILT_SOURCES = mfg_bison.h
AM_YFLAGS = -d -p mfg
AM_LFLAGS = -o$(LEX_OUTPUT_ROOT).c
noinst_LTLIBRARIES = libsrc.la
libsrc_la_SOURCES = public_api.cpp mfg_bison.yy mfg_flex.ll
pkginclude_HEADERS = public_api.h
If we didn’t want to install any headers, we’d list the headers in libsrc_la_SOURCES
. Headers that are not listed anywhere are not included in the distribution archive.
In the subdirectory some_shared_lib
, we link the convenience library, libsrc.la
, and an additional source file into a shared library, libfoobar.la
, that will be installed to /usr/local/lib
(or a different directory passed to configure
).
The Makefile.am
looks like this:
foobar/some_shared_lib/Makefile.am:
lib_LTLIBRARIES = libfoobar.la
libfoobar_la_SOURCES = shared_library.cpp
libfoobar_la_CPPFLAGS = -I$(top_srcdir)/src
libfoobar_la_LIBADD = ../src/libsrc.la
I’ve specified $(top_srcdir)/src
as an additional include directory, because it’s common to have #include
directives for sources found in src
in source files such as some_shared_lib/shared_library.cpp
. Note that for linking to the convenience library, I specifiy ../src
instead. This is because the library will be found in the build tree, not in the source tree.
Topics Not Covered
One topic that I didn’t cover but that I’m very much interested in is
- building and running a unit test suite automatically during a build.
Maybe someone of you has a simple working example?
Links
- Gary V. Vaughan, Ben Elliston, Tom Tromey and Ian Lance Taylor. GNU Automake, Autoconf, and Libtool. http://sources.redhat.com/autobook/.
- Automake Manual. http://sources.redhat.com/automake/automake.html.
- Autoconf Manual. http://www.gnu.org/software/autoconf/manual/index.html.
- The GNU Autoconf Macro Archive. http://www.gnu.org/software/ac-archive/.
- Oren Ben-Kiki. Doxample. http://ben-kiki.org/oren/doxample/.
- This article presents another Automake example: Building SWIG Python Extensions on GNU/Linux
- John Calcote. Autotools: a practitioner’s guide to Autoconf, Automake and Libtool. http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool.