Thursday, November 22, 2007

automake related

Using Automake and Autoconf with C++
Contents
* Introduction.
* make and configure
* automake and autoconf
* Sub Directories
* Example Files
* Recommended Reading
* Translations
Introduction
The automake and autoconf tools can be used to manage C++
projects under Unix. They should save a lot of time compared to
make and configure, while ensuring that your project is
structured according to GNU standards.

However, it is difficult for beginners to get started.
Hopefully, this tutorial will provide enough information for C++
programmers who are new to Unix to create their first C++
projects, while gaining a superficial understanding of what the
tools are doing.

I am not an expert on automake and autoconf, so I welcome
constructive advice on this tutorial. If you find problems with
the examples, please try to provide patches.

make and configure
The make tool can be used to manage multi-file projects. make
uses the Makefile file in your project folder, which lists the
various compiling and linking steps, targets, and dependencies.
make is well explained in C-Scene: Multi-File Projects and the
GNU Make Utility.

A configure script can be used to aid cross-platform compiling.
A suitable configure script should interpret a Makefile.in file
and then create a platform-specific Makefile file. It will do
this after performing several tests to determine the
characteristics of the platform.

This allows a user to type './configure' and then 'make' to
compile a project on his platform.

automake and autoconf
Obviously most well-written Makefiles and configure scripts will
look very similar. In fact, GNU provide guidelines about what
should be in these files. Therefore, GNU created automake and
autoconf to simplify the process and ensure that the Makefile
and configure script conform to GNU standards.

Here is a brief explanation of how these tools are used. You can
see examples of the files used by these tools in the Examples
Files section.

Note: These tools use the m4 programming language. aclocal adds
aclocal.m4 to your project directory, which contains some m4
macros which are needed.


autoconf
autoconf looks for a file called configure.ac (or,
previously, configure.in). It then creates the configure
script, based on the macros which it finds.

Whenever you add a macro to configure.ac, you should run
aclocal as well as autoconf, because aclocal scans
configure.ac to find which macros it should provide.


Lines which every configure.ac should have
Every configure.ac should have lines like the
following:

AC_INIT(hello.cc)

AM_INIT_AUTOMAKE(hello,0.1)

AC_PROG_CC

AC_PROG_CXX

AC_PROG_INSTALL

AC_OUTPUT(Makefile)

The AC_INIT macro can take any source file as an
argument. It just checks that the file is there,
which should, in turn, mean that the source
directory is there.

The AM_INIT_AUTOMAKE line adds several standard
checks. It takes the program name and version
number as arguments.

AC_PROG_CC indicates that the source code may be
in C. If the source code is C++ then we also
need AC_PROG_CXX.

AC_PROG_INSTALL will generate an install target
so that users may just type 'make install' to
install the software.

AC_OUTPUT indicates the name of the Makefile
which will be generated.

Using a Config Header
The AM_CONFIG_HEADER(config.h) line indicates
that you will be using a config.h file. autoconf
will then need a config.h.in file, which it
processes to create the config.h file. This is
#included by your source code and provides a way
for people to customise the configuration for
their platform, via #defines. config.h.in can be
generated automatically with the autoheader
tool.

However, you need a stamp-h file in your project
to ensure that automake regenerates config.h
from config.h.in. Type 'touch stamp-h' to add
this file to your project.

automake
automake looks for a file called Makefile.am. It then
creates a Makefile.in, based on the macros which it
finds. This is later used by the configure script (see
above).


GNU-style projects, or not
Because automake tries to make a GNU-style
project by default, it will add a COPYING file
and complain if some other necessary informative
text files are missing. You can add blank files
with the following command:

touch NEWS README AUTHORS ChangeLog

If you do not want these GNU-style files, then
you could add the following to your Makefile.am
instead:

AUTOMAKE_OPTIONS = foreign

Thanks to Marc van Woerkom for this suggestion.

Telling automake about your source files
Use lines like the following to name your
program and list its source files:

bin_PROGRAMS = hello

hello_SOURCES = hello.h hello.cc main.cc

Note that the second variable is prefixed with
the value of the first variable. This is a
common practice with autoconf and automake.

The Whole Process
Assuming that you have written appropriate Makefile.am
and configure.ac files (there are examples below), you
should be able to build your project by entering the
following commands:

* 'autoheader' - creates config.h.in
* 'touch NEWS README AUTHORS ChangeLog'
* 'touch stamp-h'
* aclocal - adds aclocal.m4 to directory. Defines
some m4 macros used by the auto tools.
* 'autoconf '- creates configure from
configure.ac
* 'automake' - Creates Makefile.in from
Makefile.am
* './configure' - creates Makefile from
Makefile.in >
* 'make'

Just repeat the last 5 steps to completely rebuild the
project. Most projects have an autogen.sh script that
runs everything up to the configure step.

Sub Directories
Project files should, of course, be organised in sub folders.
Ideally, all of the source files should be in a folder called
'src' in the project folder, with all of the other files (such
as makefiles, configure scripts, and readmes) separate at the
top. Projects which have several levels of folders are called
'Deep' projects. I have listed the necessary steps here, but you
should look at the Example Files section to see them in context.

When using sub-directories, you need to do the following:

1. Add a SUBDIRS entry to the top-level Makefile.am. For
example:

SUBDIRS = doc intl po src tests

Note that the directory names are separated only by spaces.

2. Add a Makefile.am file to every sub directory. The
sub-directories do not need configure.ac files. Be sure to add
the Makefiles to the list in the AC_OUPUT macro in the top-level
configure.ac.


For sub directories containing additional source code
3. Add the AC_PROG_RANLIB macro to your configure.ac.
This will allow you to build code in sub-directories
into temporary libraries, which make will then link in
with the rest of the code.

4. Add some macros to the Makefile.am of any source
directory under src. These will build a non-installing
library. You need to give the library a name beginning
with 'lib', specify the sources, and specify the
locations of any header files. For example:

noinst_LIBRARIES = libfoo.a

libfoo_a_SOURCES = foo.h foo.cc

INCLUDES = -I@top_srcdir@/src/includes

Notice that the SOURCES macro uses the library name with
an underscore instead of a dot. Also, notice the use of
the top_srcdir variable to refer to the top-level of the
project.

5. Use a LDADD_ macro in the Makefile.am of a higher
directory to link the temporary library with any code
that uses it. For example,

LDADD = foofiles/libfoo.a
For sub directories containing non-source files
3. The Makefile.am in the sub-directory should contain a
line like the following:

EXTRA_DIST = somefile.txt someotherfile.html

This tells automake that you want the files to be
distributed, but that they do not need to be compiled.

Example Files
Here are some example configure.ac and Makefile.am files. They
are sufficient to manage a C++ project which uses the Standard
Library.

See the automake and autoconf manuals for information on the
macros and variable names used in these files. I do not want to
make this seem more complicated by explaining each line of these
examples.

These examples are for a 'Deep' project with the following
structure:

helloworld_cc

configure.ac

Makefile.am

src

Makefile.am


helloworld.h

helloworld.cc

main.cc



foofiles

Makefile.am

foo.h

foo.cc
configure.ac
AC_INIT(src/hello.cc)

AM_INIT_AUTOMAKE(hello,0.1)

AM_CONFIG_HEADER(config.h)

AC_PROG_CC

AC_PROG_CXX

AC_PROG_INSTALL

AC_PROG_LIBTOOL

AC_OUTPUT(Makefile src/Makefile src/foofiles/Makefile)
Makefile.am
SUBDIRS = src
Makefile.am for the src directory
bin_PROGRAMS = hello

hello_SOURCES = hello.h hello.cc main.cc

SUBDIRS = foofiles

LDADD = foofiles/libfoo.a
Makefile.am for foofiles directory under src
noinst_LIBRARIES = libfoo.a

libfoo_a_SOURCES = foo.h foo.cc

INCLUDES = -I@top_srcdir@/

You may download a simple example project here:
helloworld_cc-0.3.tar.gz

Recommended Reading
* Building C/C++ libraries with automake and autoconf
* Using C/C++ libraries with automake and autoconf
* GNU Autoconf, Automake, and Libtool: New online book by the
creators.
* C-Scene: Multi-File Projects and the GNU Make Utility
* GNU's automake and autoconf manuals
* Learning autoconf and automake
* Learning the GNU Development tools
* Programming with GNU Software, Mike Loukides & Andy Oram

No comments:

Blog Archive