Building
a GNU Autotools Project
- The Essential Files
- The Directory Structure
- Makefile.am
- configure.in
- Generating the Output Files
- Building and Installing the
Project
- Maintaining the Input Files
- 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 <tests/project>. You will find the
project's headers and sources in the src subdirectory. There
are three files: helloworld.cc, helloworld.h and main.cc.
Makfile.am
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 <tests/project> 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 <tests/project/src> subdirectory create another text
file called Makefile.am. Add the following lines to the file and save
it:
bin_PROGRAMS
= helloworld
AM_CXXFLAGS = $(INTI_CFLAGS)
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.
configure.in
The configure.in file must in the
project's top-level directory. Change to the
<tests/project> directory and create a text file called
configure.in. Add the following lines to the file and save it:
AC_INIT(src/main.cc)
PACKAGE=helloworld
VERSION=0.1.0
AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
INTI_REQUIRED_VERSION=1.0.7
PKG_CHECK_MODULES(INTI, inti-1.0 >= $INTI_REQUIRED_VERSION)
AC_SUBST(INTI_CFLAGS)
AC_SUBST(INTI_LIBS)
AC_PROG_CXX
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:
This generates the file aclocal.m4 and adds it to the current
directory.
Next, run 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:
$
touch AUTHORS NEWS README ChangeLog |
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.
By now, the contents of the <tests/project> 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:
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:
$./autogen.sh
$ ./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: