Jan 14, 2009

Building a GNU Autotools Project


Inti Logo
« Writing Your Own Widgets Internationalization and Localization »
Building a GNU Autotools Project

1. The Essential Files
2. The Directory Structure
3. Makefile.am
4. configure.in
5. Generating the Output Files
6. Building and Installing the Project
7. Maintaining the Input Files
8. Some Helpful Links

If you're unfamiliar with the GNU Autotools and want to know how to build and maintain an Autotools project you should read this section. It will take you step-by-step through the process of creating and building a small project, and at the end provide you with some helpful links to more documentation and examples. You should also work through the next section on Internationalization and Localization. It will show you how to add international support to the project.

Autoconf and Automake provide an effective build system to maintain your software, usually on someone else's system. Automake examines source files, determines how they depend on each other, and generates a Makefile so the files can be compiled in the correct order. Autoconf permits automatic configuration of software installation, handling a large number of system quirks to increase portability. Libtool (not discussed here) is a command-line interface to the compiler and linker that makes it easy to generate static and shared libraries.

The Essential Files
The smallest project requires you provide only two files:

* Makefile.am - an input file to automake that specifies a projects build requirements: what needs to be built, and where it goes when installed.
* configure.in - an input file to autoconf that provides the macro invocations and shell code fragments autoconf uses to build a configure script.

The GNU Autotools will generate the rest of the files needed to build the project.

The Directory Structure
Before writing any code for a new project you need to decide on the directory structure the project will use.

* The top-level directory is used for configuration files, such as configure.in, and other sundry files like ChangeLog, COPY (a copy of the project license) and README.
* Any unique library should have its own subdirectory containing all headers and sources, a Makefile.am, and any other library specific files.
* The headers and sources for the main application should be in another subdirectory, typically called src.
* Other directories can include: config for intermediate files, doc for the project documentation and test for the project self-test suite.

The following steps will take you through creating and building the HelloWorld project. The top-level directory for HelloWorld is . You will find the project's headers and sources in the src subdirectory. There are three files: helloworld.cc, helloworld.h and main.cc.

You must provide a Makefile.am file for each directory in your source tree. Makefile.am for the top-level directory is simple. Create a new text file called Makefile.am in the directory. Add the following line to the file and save it:


The SUBDIRS variable is used to list the subdirectories that must be built.

Next, in the subdirectory create another text file called Makefile.am. Add the following lines to the file and save it:

bin_PROGRAMS = helloworld


helloworld_SOURCES = main.cc helloworld.cc helloworld.h
helloworld_LDADD = $(INTI_LIBS)

The bin_PROGRAMS variable specifies that we want a program called helloworld to be built and installed in the bin directory when make install is run.

The AM_CXXFLAGS macro sets the compiler flags. You should not use CXXFLAGS in Makefile.am because it's unsafe. CXXFLAGS is a user variable that users expect to be able to override.

The helloworld_SOURCES variable specifies the source files used to build the helloworld target. Note that the SOURCES variable for a target is prefixed by the name of the target, in this case helloworld.

The last variable, helloworld_LDADD, specifies the libraries that must be passed to the linker to build the target. This variable is only used by programs and libraries. Note that LDADD uses the same naming rule as the SOURCES variable.

The configure.in file must in the project's top-level directory. Change to the directory and create a text file called configure.in. Add the following lines to the file and save it:






AC_OUTPUT(Makefile src/Makefile)

The AC_INIT macro performs essential initialization for the generated configure script. It takes as an argument a filename from the source directory, to ensure that the source directory has been specified correctly.

The PACKAGE and VERSION variables declare the name and version of the package respectively.

The AM_INIT_AUTOMAKE macro does all the standard initialization required by Automake and takes two arguments, the package name and version number.

The INTI_REQUIRED_VERSION variable specifies the minimum required Inti version, in this case 1.0.7.

The PKG_CHECK_MODULES macro checks for the specified version of the Inti library and if found places the necessary include flags in $(INTI_CFLAGS) and the libraries to link with $(INTI_LIBS). If the correct version is not found configure will report an error.

The AC_PROG_CXX checks for the C++ compiler and sets the variables CXX, GXX and CXXFLAGS.

The last macro AC_OUTPUT must be called at the end of configure.in to create the Makefiles.

Generating the Output Files
Now we need to generate the required output files from the two input files configure.in and Makefile.am. First we need to collect all the macro invocations in configure.in that Autoconf will need to build the configure script. This is done with the following command:

$ aclocal

This generates the file aclocal.m4 and adds it to the current directory.

Next, run autoconf:

$ autoconf

After running autoconf you will find the configure script in the current directory. It's important to run aclocal first because automake relies on the contents on configure.in and aclocal.m4.

There are a few files that the GNU standard says must be present in the top-level directory, and if not found Automake will report an error. Enter the following command to create these files:


Now we can run automake to create Makefile.in. The --add-missing argument copies some boilerplate files from your Automake installation into the current directory.

$ automake --add-missing

By now, the contents of the directory should be looking a lot like the top-level directory of a GNU package you may have installed before:

aclocal.m4 autom4te.cache config.h.in configure.in depcomp install-sh Makefile.in mkinstalldirs README
AUTHORS ChangeLog configure COPYING INSTALL Makefile.am missing NEWS src

Building and Installing the Project
At this point you should be able to package up your source tree in a tarball and give it to other users to install on their own systems. A user just has to unpack the tarball and run the following commands:

$ ./configure --prefix=some_directory
$ make
$ make install

If you run the above commands and look in your bin directory you will find helloworld. Have a look at the size of the executable. Wow! Its 588 kbytes. That's because it contains all the debugging and compiler symbols needed to debug the program.

Now run the following command:

$ make install-strip

If you look at the size of helloworld now it's a lot smaller, only 35.7 kbytes. The command make install-strip strips out all the debugging symbols. The resulting executable is much smaller and faster but you won't be able to debug the program. As a rule, you should only strip a program when its stable.

Maintaining the Input Files
Everytime you edit any of the GNU Autotools input files in your package, you must regenerate the output files. If you add a new source file to the helloworld_SOURCES variable in Makefile.am you must regenerate Makefile.in. If you are building your package you will need to rerun configure to regenerate the Makefile's. Many project maintainers put the necessary commands to do this into a script called autogen.sh and run this script whenever the output files need to be regenerated.

Create a text file called autogen.sh in the top-level directory and make sure you change its file mode to make it executable. Add the following commands to the file and save it:

#! /bin/sh

aclocal \
&& automake --add-missing \
&& autoconf

Now you can easily run the following commands to update your project's output files, and rebuild the project:

$ ./configure --prefix=/some_directory
$ make
$ make install

Some helpful links
This tutorial should get you started using the GNU Autotools and that should be enough, for a while. Eventually you will need to know more, like how to build a shared library or what macros should be added to configure.in. I found the following links very useful:

* Using Automake and Autoconf with C++
* Using C/C++ libraries with Automake and Autoconf
* Building C/C++ libraries with automake and autoconf
* GNU Autoconf, Automake, and Libtool
* GNU's automake and autoconf manuals

« Writing Your Own Widgets Index
Internationalization and Localization »

No comments: