automake
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: "Autotools Introduction" chapter draft (16 pages long)


From: Alexandre Duret-Lutz
Subject: RFC: "Autotools Introduction" chapter draft (16 pages long)
Date: Sat, 12 Aug 2006 23:45:50 +0200
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/22.0.50 (gnu/linux)

Hi Folks,

I need your help!

Over the last weeks I've been writing an introductory chapter
for the Automake manual.  Now I could use some proofreading
eyes, especially since I'm a foreigner.  Other suggestions
welcome too, of course.

My objective is (at least) threefold:

  - I want to present to GNU Build System in a way which makes
    people eager to use the Autotools.

  - I would like to use this opportunity to present several uses
    of the build system that a maintainer should have in mind
    when hacking his package, but often do not even know about.
    (I'm often taken aback by Automake users who post to this
    list not knowing what a VPATH build.  I really shouldn't be
    surprised: there is not a single place in the manual that
    takes to time to details what that is.)

  - I want to get rid of the outdated "GNU Hello" example later
    in the manual.  GNU Hello is now too complex to be useful in
    a tutorial.    

I'm not yet 100% sure how to plug this chapter into the existing
documentation.  Presently, I've inserted it right after the
first chapter that introduces Automake.  Introducing Automake
before Introducing the Autotools may sound weird, but I thing
that it is nice to have a very short chapter giving the reader a
sense of what Automake is about (even if that can be mostly
Chinese to some newcomer) before talking about the GNU Build
System and the Autotools in general.

The structure of this chapter is mostly based on the first
slides of my (unredacted) Autotools tutorial at
http://www-src.lip6.fr/~Alexandre.Duret-Lutz/autotools.html 

I'm undecided whether I should mention this tutorial in the
manual.  Some people who commented on the tutorial suggested I
did this, but I feared it might not be very diplomatic to decide
that this tutorial was worth being mentioned and not
others... Now it would be a bit different: it might be useful to
now that there exist some teaching material that illustrates
this chapter and then go far beyond it.

The text still lacks a bit of cross referencing, and I also have
to add many entries into the indexes.  But that should not
prevent useful comments.

For those who want to print it, a postscript version is available
at http://www-src.lip6.fr/~Alexandre.Duret-Lutz/dl/am-chap2.ps.gz

You'll find a text version below, it is easier to quote.

If you to help and comment upon this draft, please DO NOT reply
privately.  It can't seem to deal with private mail, please bear
with me.  I you feel that pointing out my missing "s"s and other
blunders will pollute this list, feel free to divert your answer
to address@hidden

Thanks !



2 An Introduction to the Autotools
**********************************

If you are new to Automake, maybe you know that it is part of a set of
tools called _The Autotools_.  Maybe you've already delved into a
package full of files named `configure', `configure.ac', `Makefile.in',
`Makefile.am', `aclocal.m4', ...  some of them claiming to be
_generated by_ Autoconf or Automake.  But the exact purpose of these
files and their relations is probably fuzzy.  The goal of this chapter
is to introduce you this machinery, to show you how it works and how
powerful it is.  If you've never installed or seen such a package, do
not worry: this chapter will walk you through it.

2.1 Introducing the GNU Build System
====================================

It is a truth universally acknowledged, that a developer in possession
of a new package, must be in want of a build system.

   In the Unix world, such a build system is traditionally achieved
using the command `make' (*note Overview: (make)Top.).  The developer
expresses the recipe to build his package in a `Makefile'.  This file
is a set of rules to build the files in the package.  For instance the
program `prog' may be built by running the linker on the files
`main.o', `foo.o', and `bar.o'; the file `main.o' may be built by
running the compiler on `main.c'; etc.  Each time `make' is run, it
reads `Makefile', checks the existence and modification time of the
files mentioned, decides what files need to be built (or rebuilt), and
run the associated commands.

   When a package needs to be built on a different platform than the one
it was developed on, its `Makefile' usually needs to be adjusted.  For
instance the compiler may have another name or require more options.
In 1991, David J. MacKenzie got tired of customising `Makefile' for the
20 platforms he had to deal with.  Instead, he handcrafted a little
shell script called `configure' to automatically adjust the `Makefile'
(*note Genesis: (autoconf)Genesis.).  Compiling his package was now as
simple as running `./configure && make'.

   Today this process has been standardised in the GNU project.  The GNU
Coding Standards (*note The Release Process: (standards)Managin
Releases.) explains how each package of the GNU project should have
package of the GNU project should have such a `configure' script, and
the minimal interface it should have.  The `Makefile' too should follow
some established conventions.  The result?  A unified build system that
makes all packages almost indistinguishable by the installer.  In its
most simple scenario, all the installer has to do is to unpack the
package, run `./configure && make && make install', and repeat with the
next package to install.

   We call this build system the "GNU Build System", since it was grown
out of the GNU project.  However it is used by a vast number of other
packages: following any existing convention has its advantages.

   The Autotools are tools that will create a GNU Build System for your
package.  Autoconf mostly focuses on `configure' and Automake on
`Makefile's.  It is entirely possible to create a GNU Build System
without the help of these tools.  However it is rather burdensome and
error-prone.  We will discuss this again after some illustration of the
GNU Build System in action.

2.2 Use Cases for the GNU Build System
======================================

In this section we explore several use cases for the GNU Build System.
You can replay all these examples on the `amhello-1.0.tar.gz' package
distributed with Automake.  If Automake is installed on your system,
you should find a copy of this file in
`PREFIX/share/doc/automake/amhello-1.0.tar.gz', where PREFIX is the
installation prefix specified during configuration (PREFIX defaults to
`/usr/local', however if Automake was installed by some GNU/Linux
distribution it most likely has been set to `/usr').  If you do not
have a copy of Automake installed, you can find a copy of this file
inside the `doc/' directory of the Automake package.

   Some of the following use cases present features that are in fact
extensions to the GNU Build System.  Read: they are not specified by
the GNU Coding Standard, but they are nonetheless part of the build
system created by the Autotools.  To keep things simple we do not make
the difference.  Our objective is to show you many of the features that
the build system created by the Autotools will offer to you.

2.2.1 Basic Installation
------------------------

The most common installation procedure looks as follows.

     ~ % tar zxf amhello-1.0.tar.gz
     ~ % cd amhello-1.0
     ~/amhello-1.0 % ./configure
     ...
     config.status: creating Makefile
     config.status: creating src/Makefile
     ...
     ~/amhello-1.0 % make
     ...
     ~/amhello-1.0 % make check
     ...
     ~/amhello-1.0 % su
     Password:
     /home/adl/amhello-1.0 # make install
     ...
     /home/adl/amhello-1.0 # exit
     ~/amhello-1.0 % make installcheck
     ...

   The user first unpacks the package, and then `cd' into the newly
created directory to run the `configure' script.  This script probes
the system for various features, and finally create the `Makefile's.
In this toy example there are only two `Makefile's, but in real-world
project there may be many more, usually one `Makefile' per directory.

   It is now possible to run `make'.  This will construct all the
programs, libraries, and scripts that need to be constructed for the
package.  In our example, this compiles the `hello' program.  All files
are constructed in place, in the source tree; we will see later how
this can be changed.

   `make check' causes the package's tests to be run.  This step is not
mandatory, but it is often good to make sure the programs that have
been built behave as they should, before you decide to install them.
Our example does not contain any test, so running `make check' is a
no-op.

   After every thing has been built, and maybe tested, it is time to
install them on the system.  That means copying the programs,
libraries, header files, scripts, and other data files, from the source
directory to their final destination on the system.  The command `make
install' will do that.  However by default everything will be installed
in subdirectories of `/usr/local': binaries will go into
`/usr/local/bin', libraries will end into `/usr/local/lib', etc.  This
destination is usually not writable by any user, so we assume that we
have to become root before we can run `make install'.  In our example,
running `make install' will copy the program `hello' into
`/usr/local/bin' and `README' into `/usr/local/share/doc/amhello'.

   A last and optional step is to run `make installcheck'.  This
command may run tests on the installed files.  `make check' tests the
files in the source tree while `make installcheck' tests their
installed copies.  The tests run by the latter can be different from
those run by former: there are tests that cannot be run in the source
tree.  Conversely, some packages are set up so that `make installcheck'
will run the very same tests as `make check', only on different files
(non-installed vs. installed).  It can make a difference, for instance
when the source tree's layout is different than that of the
installation, furthermore it may help to diagnose an incomplete
installation.

   Presently most packages do not have any `installcheck' tests because
the existence of `installcheck' is little known, and its usefulness is
neglected.  Our little toy package is no better: `make installcheck'
does nothing.

2.2.2 Standard `Makefile' Targets
---------------------------------

So far we have come across four ways to run `make' in the GNU Build
System: `make', `make check', `make install', and `make installcheck'.
The words `check', `install', and `installcheck', passed as argument to
`make' are called "targets".  `make' is a shorthand for `make all',
`all' being the default target.

   Here is a list of the most useful targets that the GNU Coding
Standards specify.

`make all'
     Build programs, libraries, documentation, etc.  (Same as `make'.)

`make install'
     Install what needs to be installed, copying the files from the
     package's tree to system-wide directories.

`make install-strip'
     Same as `make install', then strip debugging symbols.  Some users
     like to trade space for useful bug reports...

`make uninstall'
     The opposite of `make install': erase the installed files.  (This
     needs to be run from the same build tree that was installed.)

`make clean'
     Erase from the build tree the files built by `make all'.

`make distclean'
     Additionally erase anything `./configure' created.

`make check'
     Run the test suite, if any.

`make installcheck'
     Check the installed programs or libraries, if supported.

`make dist'
     Recreate `PACKAGE-VERSION.tar.gz' from all the source files.

2.2.3 Standard Directory Variables
----------------------------------

The GNU Coding Standards also specify a hierarchy of variables to
denote installation directories.

Directory variable   Default value
------------------------------------------------- 
PREFIX               `/usr/local'
  EXEC-PREFIX        `PREFIX'
    BINDIR           `EXEC-PREFIX/bin'
    LIBDIR           `EXEC-PREFIX/lib'
    ...              
  INCLUDEDIR         `PREFIX/include'
  DATAROOTDIR        `PREFIX/share'
    DATADIR          `DATAROOTDIR'
    MANDIR           `DATAROOTDIR/man'
    INFODIR          `DATAROOTDIR/info'
    DOCDIR           `DATAROOTDIR/doc/PACKAGE'
  ...                

   Each of these directories has a role which is often obvious from its
name.  In a package, any installable file will be installed in one of
these directories.  For instance in `amhello-1.0', the program `hello'
is to be installed in BINDIR, the directory for binaries.  The default
value for this directory is `/usr/local/bin', but the user can supply a
different value when calling `configure'.  Also the file `README' will
be installed into DOCDIR, which defaults to
`/usr/local/share/doc/amhello'.

   A user who wish to install a package on his own account could proceed
as follows:

     ~/amhello-1.0 % ./configure --prefix ~/usr
     ...
     ~/amhello-1.0 % make
     ...
     ~/amhello-1.0 % make install
     ...

   This would install `~/usr/bin/hello' and
`~/usr/share/doc/amhello/README'.

   The list of all such directory options is shown by `./configure
--help'.

2.2.4 Standard Configuration Variables
--------------------------------------

The GNU Coding Standards also define a set of standard configuration
variables used during the build.  Here are some:

`CC'
     C compiler command

`CFLAGS'
     C compiler flags

`CXX'
     C++ compiler command

`CXXFLAGS'
     C++ compiler flags

`LDFLAGS'
     linker flags

`CPPFLAGS'
     C/C++ preprocessor flags

...

   `configure' usually does a good job at setting appropriate values
for these variables, but there are cases where you may want to override
them.  For instance you may have several versions of a compiler
installed and would like to use another one, you may have header files
installed outside the default search path of the compiler, or even
libraries out of the way of the linker.

   Here is how one would call `configure' to force it to use `gcc-3' as
C compiler, use header files from `~/usr/include' when compiling, and
libraries from `~/usr/lib' when linking.

     ~/amhello-1.0 % ./configure --prefix ~/usr CC=gcc-3 \
     CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib

   Again, a full list of these variables appears in the output of
`./configure --help'.

2.2.5 Overriding Default Configuration Setting with `config.site'
-----------------------------------------------------------------

When installing several packages using the same setup, it can be
convenient to create a `config.site' to capture common settings.  If a
file named `PREFIX/share/config.site' exists, `configure' will source
it at the beginning of its execution.

   Recall the command from the previous section:

     ~/amhello-1.0 % ./configure --prefix ~/usr CC=gcc-3 \
     CPPFLAGS=-I$HOME/usr/include LDFLAGS=-L$HOME/usr/lib

   Assuming we are installing many package in `~/usr', and will always
want to use these definition of `CC', `CPPFLAGS', and `LDFLAGS', we can
automatize this by creating the following `~/usr/share/config.site'
file:

     test -z "$CC" && CC=gcc-3
     test -z "$CPPFLAGS" && CPPFLAGS=-I$HOME/usr/include
     test -z "$LDFLAGS" && LDFLAGS=-L$HOME/usr/lib

   Now any time a `configure' script is using the `~/usr' prefix, it
will execute the above `config.site' and define these three variables.

     ~/amhello-1.0 % ./configure --prefix ~/usr
     configure: loading site script /home/adl/usr/share/config.site
     ...

   *Note Setting Site Defaults: (autoconf)Site Defaults, for more
information about this feature.

2.2.6 Parallel Build Trees (a.k.a. VPATH Builds)
------------------------------------------------

The GNU Build System distinguishes two trees : the source tree, and the
build tree.

   The source tree is rooted in the directory containing `configure',
it contains all the sources files (those that are distributed), and may
be arranged using several subdirectories.

   The build tree is rooted in the directory where the `configure' were
run, and is populated with all object files, programs, libraries, and
other derived files built from the sources (and hence not distributed).
The build tree usually has the same subdirectory layout as the source
tree; these subdirectories are created automatically by the build
system.

   If `configure' is executed in its own directory, the source and
build trees are combined: derived files are constructed in the same
directory as their sources.  This was the case in our first
installation example (*note Basic Installation::).

   A common request from users is that they want to confine all derived
files to a single directory, to keep their source directories
uncluttered.  Here is how we could run `configure' to build everything
in a subdirectory called `build/'.

     ~ % tar zxf ~/amhello-1.0.tar.gz
     ~ % cd amhello-1.0
     ~/amhello-1.0 % mkdir build && cd build
     ~/amhello-1.0/build % ../configure
     ...
     ~/amhello-1.0/build % make
     ...

   These setups, where source and build trees are different, are often
called "parallel builds" or "VPATH builds".  The word _parallel_ is a
reference to the way the build tree shadows the source tree, it is not
about some concurrency in the way build commands are run.  _VPATH_ is
the name of the `make' feature used by the `Makefile's to allow these
builds (*note `VPATH': Search Path for All Prerequisites: (make)General
Search.).

   VPATH builds have other interesting uses.  One is to build the same
sources with multiple configurations.  For instance:

     ~ % tar zxf ~/amhello-1.0.tar.gz
     ~ % cd amhello-1.0
     ~/amhello-1.0 % mkdir debug optim && cd debug
     ~/amhello-1.0/debug % ../configure CFLAGS='-g -O0'
     ...
     ~/amhello-1.0/debug % make
     ...
     ~/amhello-1.0/debug % cd ../optim
     ~/amhello-1.0/optim % ../configure CFLAGS='-O3 -fomit-frame-pointer'
     ...
     ~/amhello-1.0/optim % make
     ...

   With network file systems, a similar approach can be used to build
the same sources on different machines.  For instance suppose that the
sources are installed on a directory shared by two hosts: `HOST1' and
`HOST2', maybe different platforms.

     ~ % cd /nfs/src
     /nfs/src % tar zxf ~/amhello-1.0.tar.gz

   On the first host you could create a local build directory:
     [HOST1] ~ % mkdir /tmp/amh && cd /tmp/amh
     [HOST1] /tmp/amh % /nfs/src/amhello-1.0/configure
     ...
     [HOST1] /tmp/amh % make && sudo make install
     ...

   On the second host, you would do exactly the same, possibly at same
time:
     [HOST2] ~ % mkdir /tmp/amh && cd /tmp/amh
     [HOST2] /tmp/amh % /nfs/src/amhello-1.0/configure
     ...
     [HOST2] /tmp/amh % make && sudo make install
     ...

   In this scenario, nothing forbids the `/nfs/src/amhello-1.0'
directory from being read-only.  In fact VPATH builds are also a means
of building packages from a read-only medium such as a CD-ROM.  (The
FSF used to sell CD-ROM with unpacked source code, before the GNU
project grew so big.)

2.2.7 Two-Part Installation
---------------------------

In our last example (*note VPATH Builds::), a source tree was shared by
two hosts, but compilation and installation were done separately on
each host.

   The GNU Build System also supports networked setups where part of the
installed files should be shared amongst multiple hosts.  It does so by
distinguishing architecture-dependent files from
architecture-independent files, and providing two `Makefile' targets to
install each of these classes of files.

   These targets are `install-exec' for architecture-dependent files
and `install-data' for architecture-independent files.  The command we
used up to now, `make install', can be thought as a shorthand for `make
install-exec install-data'.

   From the GNU Build System point of view, the distinction between
architecture-dependent files and architecture-independent files is
based exclusively on the directory variable used to specify their
installation destination.  In the list of directory variables we
provided earlier (*note Standard Directory Variables::) all the
variables based on EXEC-PREFIX designate architecture-dependent
directories whose files will be installed by `make install-exec'.  The
others designate architecture-independent directories and will serve
files installed by `make install-data'.  *Note Install::, for more
details.

   Here is how we could revisit our two-host installation example,
assuming that (1) we want to install the package directly in `/usr',
and (2) the directory `/usr/share' is shared by the two hosts.

   On the first host we would run
     [HOST1] ~ % mkdir /tmp/amh && cd /tmp/amh
     [HOST1] /tmp/amh % /nfs/src/amhello-1.0/configure --prefix /usr
     ...
     [HOST1] /tmp/amh % make && sudo make install
     ...

   On the second host, however, we need only to install the
architecture-specific files.
     [HOST2] ~ % mkdir /tmp/amh && cd /tmp/amh
     [HOST2] /tmp/amh % /nfs/src/amhello-1.0/configure --prefix /usr
     ...
     [HOST2] /tmp/amh % make && sudo make install-exec
     ...

   In packages that have installation checks, it would make sense to run
`make installcheck' (*note Basic Installation::) to verify that the
package works correctly despite the apparent partial installation.

2.2.8 Cross Compilation
-----------------------

To "cross compile" is to build on one platform a binary that will be
run on another platform.  When speaking of cross-compilation, it is
important to distinguish between the "build platform" one which the
compilation is performed, and the "host platform" on which the
resulting executable is expected to run.  The following `configure'
options are used to specify each of them:

`--build=BUILD'
     The system on which the package is built.

`--host=HOST'
     The system where built programs & libraries will run.

   When the `--host' is used, `configure' will search for the cross
compiling suite for this platform.  Cross compilation tools have their
target architecture as prefix of their name.  For instance my cross
compiler for MinGW32 has its binaries called `i586-mingw32msvc-gcc',
`i586-mingw32msvc-ld', `i586-mingw32msvc-as', etc.

   Here is how we could build `amhello-1.0' for `i586-mingw32msvc' on a
GNU/Linux PC.

     ~/amhello-1.0 % ./configure --build i686-pc-linux-gnu --host 
i586-mingw32msvc
     checking for a BSD-compatible install... /usr/bin/install -c
     checking whether build environment is sane... yes
     checking for gawk... gawk
     checking whether make sets $(MAKE)... yes
     checking for i586-mingw32msvc-strip... i586-mingw32msvc-strip
     checking for i586-mingw32msvc-gcc... i586-mingw32msvc-gcc
     checking for C compiler default output file name... a.exe
     checking whether the C compiler works... yes
     checking whether we are cross compiling... yes
     checking for suffix of executables... .exe
     checking for suffix of object files... o
     checking whether we are using the GNU C compiler... yes
     checking whether i586-mingw32msvc-gcc accepts -g... yes
     checking for i586-mingw32msvc-gcc option to accept ANSI C...
     ...
     ~/amhello-1.0 % make
     ...
     ~/amhello-1.0 % cd src; file hello.exe
     hello.exe: MS Windows PE 32-bit Intel 80386 console executable not 
relocatable

   The `--host' and `--build' options are usually all we need for
cross-compiling.  The only exception is if the package being built is
itself a cross-compiler: we need a third option to specify its target
architecture.

`--target=TARGET'
     When building compiler tools: the system for which the tools will
     create output.

   For instance when installing GCC, the GNU Compiler Collection, we can
use `--target=TARGET' to specify that we want to build GCC as a
cross-compiler for TARGET.  Mixing `--build' and `--target', we can
actually cross-compile a cross-compiler; such a three-way
cross-compilation is known as a "Canadian cross".

   *Note Specifying the System Type: (autoconf)Specifying Names, for
more information about these `configure' options.

2.2.9 Renaming Programs at Install Time
---------------------------------------

The GNU build system provides means to automatically rename executables
before they are installed.  This is especially convenient when
installing a GNU package on a system that already has a proprietary
implementation you do not want to overwrite.  For instance you may want
to install GNU `tar' as `gtar' so you can distinguish it from your
vendor's `tar'.

   This can be done using one of these three `configure' options.

`--program-prefix=PREFIX'
     Prepend PREFIX to installed program names.

`--program-suffix=SUFFIX'
     Append SUFFIX to installed program names.

`--program-transform-name=PROGRAM'
     Run `sed PROGRAM' on installed program names.

   The following commands would install `hello' as
`/usr/local/bin/test-hello', for instance.

     ~/amhello-1.0 % ./configure --program-prefix test-
     ...
     ~/amhello-1.0 % make
     ...
     ~/amhello-1.0 % sudo make install
     ...

2.2.10 Building Binary Packages Using DESTDIR
---------------------------------------------

The GNU build system's `make install' and `make uninstall' interface
does not exactly fits the needs of a system administrator who has to
deploy and upgrade packages on lots of hosts.  In other words, the GNU
build system does not replace a package manager.

   The `DESTDIR' variable can be used when creating binary packages
containing a snapshot of all the files to be installed.  The package
should be configured as if it was going to be installed in its final
location (e.g., `--prefix /usr'), but when running `make install' the
`DESTDIR' should be set to the name of an empty directory in which all
the installation will be diverted.

     ~/amhello-1.0 % ./configure --prefix /usr
     ...
     ~/amhello-1.0 % make
     ...
     ~/amhello-1.0 % make DESTDIR=$HOME/inst install
     ...
     ~/amhello-1.0 % cd ~/inst
     ~/inst % tar zcvf ~/amhello-1.0-i686.tar.gz .
     ./
     ./usr/
     ./usr/bin/
     ./usr/bin/hello
     ...

   After this example, `amhello-1.0-i686.tar.gz' is ready to be
uncompressed in `/' on many hosts.

   Note that when building packages for several architectures, it might
be convenient to use `make install-data' and `make install-exec' (*note
Two-Part Install::) to gather architecture-independent files in a
single package.

2.2.11 Preparing Distributions
------------------------------

We have already mentioned `make dist'.  This target collects all your
source files, and the necessary parts of the build system, to create a
tarball named `PACKAGE-VERSION.tar.gz'

   Another, more useful command is `make distcheck'.  The `distcheck'
target constructs `PACKAGE-VERSION.tar.gz' just as well as `dist', but
it additionally ensures most of the use-cases presented so far work.

   * It attempts a full compilation of the package (*note Basic
     Installation::), unpacking the newly constructed tarball, running
     `make', `make check', `make install', as well as `make
     installcheck', and even `make dist',

   * it tests VPATH builds with read-only source tree (*note VPATH
     Builds::),

   * it makes sure `make clean', `make distclean', and `make uninstall'
     do not omit any file (*note Standard Targets::),

   * and it checks that `DESTDIR' installations work (*note DESTDIR::).

   Releasing a package that fails `make distcheck' means that one of
the scenario we presented won't work and some users will be
disappointed.  Therefore it is a good practice to release a package
only after a successful `make distcheck'.  This of course does not
imply that the package will be flawless, but at least it will prevent
some of the embarrassing errors you may find in packages released by
people who have never heard about `distcheck' (like `DESTDIR' not
working because of a typo, or a distributed file being erased by `make
clean', or even `VPATH' builds not working).

   *Note Dist::, for more information about `distcheck'.

2.2.12 Automatic Dependency Tracking
------------------------------------

Dependency tracking is performed as a side-effect of compilation.  Each
time the build system compiles a source file, it computes its list of
dependencies (in C these are the header files included by the source
being compiled).  Later, any time `make' is run and a dependency appear
to have changed, the dependent files will be rebuilt.

   When `configure' is executed, you can see it probing each compiler
for the dependency mechanism it supports (several mechanisms can be
used):

     ~/amhello-1.0 % ./configure --prefix /usr
     ...
     checking dependency style of gcc... gcc3
     ...

   Because dependencies are only computed as a side-effect of the
compilation, no dependency information exist the first time a package
is built.  This is OK because all the files need to be built anyway:
`make' does not have to decide which files need to be rebuilt.  In
fact, dependency tracking is completely useless for one-time builds and
there is a `configure' option to disable this.

`--disable-dependency-tracking'
     Speed up one-time builds.

   Some compilers do not offer any practical way to derive the list of
dependencies as a side-effect of the compilation, requiring a separate
run (maybe of another tool) to compute these dependencies.  The
performance penalty implied my these methods is important enough to
disable them by default.  The option `--enable-dependency-tracking'
must be passed to `configure' to active them.

`--enable-dependency-tracking'
     Do not reject slow dependency extractors.

   *Note Dependency Tracking Evolution::, for some discussion about the
different dependency tracking schemes used by Automake over the years.

2.2.13 Nested Packages
----------------------

Although nesting packages isn't something we would recommend to someone
who is discovering the Autotools, it is a nice feature worthy of
mention in this small advertising tour.

   Autoconfiscated packages (that means packages whose build system have
been created by Autoconf and friends) can be nested to arbitrary depth.

   A typical setup is that a package A will distribute one of the
library it needs in a subdirectory.  This library B is a complete
package with its own GNU Build System.  The `configure' script of A will
run the `configure' script of B as part of its execution, building and
installing A will also build and install B.  Generating a distribution
for A will also include B.

   It is possible to gather several package like this.  GCC is an heavy
user of this feature.  This gives installers a single package to
configure, build and install, while it allows developers to work on
subpackages independently.

   When configuring nested packages, the `configure' options given to
the top-level `configure' are passed recursively to nested
`configure's.  A package that do not understand an option will ignore
it, assuming it is meaningful to some other package.

   The command `configure --help=recursive' can be used to display the
options supported by all the included packages.

   *Note Subpackages::, for an example setup.

2.3 How Autotools Help
======================

There are several reason why you may not want to implement the GNU Build
System yourself (read: write a `configure' script and `Makefile's
yourself).

   * As we have seen, the GNU Build System has a lot of features (*note
     Use Cases::).  Some users may expect features you have not
     implemented you did not need them.

   * Implementing these feature portably is difficult, and exhausting.
     Think portable shell scripts, portable `Makefile's, on systems you
     may not have handy.  *Note Portable Shell Programming:
     (autoconf)Portable Shell, to convince yourself.

   * You will have to upgrade your setup to follow changes to the GNU
     Coding Standards.

   The GNU Autotools take all this burden off your back and provide:

   * Tools to create a portable, complete, and self-contained, GNU Build
     System, from simple instructions.  _Self-contained_ meaning the
     resulting build system does not require the GNU Autotools.

   * A central place where fixes and improvements are made: a bug-fix
     for a portability issue will benefit every package.

   Yet there also exist reasons why you may want NOT to use the
Autotools.... For instance you may be already using (or used to)
another incompatible build system.  Autotools will only be useful if
you do accept the concepts of GNU Build System.  People who have their
own idea of how a build system should work will feel frustrated by the
Autotools.

2.4 A Small Hello World
=======================

In this section we recreate the `amhello-1.0' package from scratch.
The first subsection shows how to call the Autotools to instantiate the
GNU Build System, while the second explains the meaning of the
`configure.ac' and `Makefile.am' files read by the Autotools.

2.4.1 Creating `amhello-1.0.tar.gz'
-----------------------------------

Here is how we can recreate `amhello-1.0.tar.gz' from scratch.  The
package is simple enough so that we will only need to write 5 files.
(You may copy them from the final `amhello-1.0.tar.gz' that is
distributed with Automake if you do not want to write them.)

   Create the following files in an empty directory.

   * `src/main.c' is the source file for the `hello' program.  We store
     it in the `src/' subdirectory, because later if the package
     evolves, it will ease the addition of a `man/' directory for man
     pages, a `data/' directory for data files, etc.
          ~/amhello % cat src/main.c
          #include <config.h>
          #include <stdio.h>

          int
          main (void)
          {
            puts ("Hello World!");
            puts ("This is " PACKAGE_STRING ".");
            return 0;
          }

   * `README' contains some very limited documentation for our little
     package.
          ~/amhello % cat README
          This is a demonstration package for GNU Automake.
          Type `info Automake' to read the Automake manual.

   * `Makefile.am' and `src/Makefile.am' contain Automake instructions
     for these two directories.

          ~/amhello % cat src/Makefile.am
          bin_PROGRAMS = hello
          hello_SOURCES = main.c
          ~/amhello % cat Makefile.am
          SUBDIRS = src
          dist_doc_DATA = README

   * Finally, `configure.ac' contains Autoconf instructions to create
     the `configure' script.

          ~/amhello % cat configure.ac
          AC_INIT([amhello], [1.0], address@hidden)
          AM_INIT_AUTOMAKE([-Wall -Werror foreign])
          AC_PROG_CC
          AC_CONFIG_HEADERS([config.h])
          AC_CONFIG_FILES([
           Makefile
           src/Makefile
          ])
          AC_OUTPUT

   Once you have these five files, it is time to run the Autotools to
instantiate the build system.  Do this using the `autoreconf' command
as follows:

     ~/amhello % autoreconf --install
     configure.ac: installing `./install-sh'
     configure.ac: installing `./missing'
     src/Makefile.am: installing `./depcomp'

   At this point the build system is complete.

   In addition to the three scripts mentioned in its output, you can see
that `autoreconf' created four other files: `configure', `config.h.in',
`Makefile.in', and `src/Makefile.in'.  The latter three files are
templates that will be adapted to the system by `configure', under them
names `config.h', `Makefile', and `src/Makefile'.  Let's do this:

     ~/amhello % ./configure
     checking for a BSD-compatible install... /usr/bin/install -c
     checking whether build environment is sane... yes
     checking for gawk... no
     checking for mawk... mawk
     checking whether make sets $(MAKE)... yes
     checking for gcc... gcc
     checking for C compiler default output file name... a.out
     checking whether the C compiler works... yes
     checking whether we are cross compiling... no
     checking for suffix of executables...
     checking for suffix of object files... o
     checking whether we are using the GNU C compiler... yes
     checking whether gcc accepts -g... yes
     checking for gcc option to accept ISO C89... none needed
     checking for style of include used by make... GNU
     checking dependency style of gcc... gcc3
     configure: creating ./config.status
     config.status: creating Makefile
     config.status: creating src/Makefile
     config.status: creating config.h
     config.status: executing depfiles commands

   You can see `Makefile', `src/Makefile', and `config.h' being created
at the end after `configure' has probed the system.  It is now possible
to run all the targets we wish (*note Standard Targets::).  For
instance:

     ~/amhello % make
     ...
     ~/amhello % src/hello
     Hello World!
     This is amhello 1.0.
     ~/amhello % make distcheck
     ...
     =============================================
     amhello-1.0 archives ready for distribution:
     amhello-1.0.tar.gz
     =============================================

   Note that running `autoreconf' is only needed initially when the GNU
Build System does not exist.  When you later changes some instructions
in a `Makefile.am' or `configure.ac', the relevant part of the build
system will be regenerated automatically when you execute `make'.

   `autoreconf' is a script that calls `autoconf', `automake', and a
bunch of other commands, in the right order.  If you are beginning with
these tools, it is not important to figure out in which order all these
tools should be invoked and why.  However because Autoconf and Automake
have separate manuals, the important point to understand is that
`autoconf' is in charge of creating `configure' from `configure.ac',
while `automake' is in charge of creating `Makefile's from
`Makefile.am's and `configure.ac' too.  This should at least direct you
to the correct manual when seeking answers.

2.4.2 `amhello-1.0' Explained
-----------------------------

Let us begin with the contents of `configure.ac'.

     AC_INIT([amhello], [1.0], address@hidden)
     AM_INIT_AUTOMAKE([-Wall -Werror foreign])
     AC_PROG_CC
     AC_CONFIG_HEADERS([config.h])
     AC_CONFIG_FILES([
      Makefile
      src/Makefile
     ])
     AC_OUTPUT

   This file is read by both `autoconf' (to create `configure.ac') and
`automake' (to create the various `Makefile.in's).  It contains a
series of M4 macros that will be expansed as shell code to finally form
the `configure' script.  We will not elaborate on the syntax of this
file, because the Autoconf manual has a whole section about it (*note
Writing `configure.ac': (autoconf)Writing configure.ac.).

   The macros that starts with `AC_' are Autoconf macros, documented in
the Autoconf manual (*note Autoconf Macro Index: (autoconf)Autoconf
Macro Index.).  The macros that starts with `AM_' are Automake macros,
documented later in this manual (*note Macro Index::).

   The first two lines of `configure.ac' initialize Autoconf and
Automake.  `AC_INIT' takes in parameters the name of the package, its
version number, and a contact address for bug-reports about the package
(this address is output at the end of `./configure --help' for
instance).  When adapting this setup to your own package, by all means
please do not blindly copy Automake's address: use the mailing list of
your package, or your own mail address.

   The argument to `AM_INIT_AUTOMAKE' is a list of options for
`automake' (*note Options::).  `-Wall' and `-Werror' ask `automake' to
turn on all warnings and report them as errors.  We are speaking of
*Automake* warnings here, such as dubious instructions in
`Makefile.am', this has absolutely nothing to do with how the compiler
will be called even though it may support options with similar names.
Using `-Wall -Werror' is a safe setting when starting to work on a
package: you do not want to miss any issue.  Later you may decide to
relax things a bit.  The `foreign' option tells Automake that this
package will not follow the GNU Standards.  GNU packages should always
distribute additional files such as `ChangeLog', `AUTHORS', etc.  We do
not want `automake' to complain about these missing files in our small
example.

   The `AC_PROG_CC' line causes the `configure' script to search for a
C compiler and define the variable `CC' with its name.  The
`src/Makefile.in' file generated by Automake uses the variable `CC' to
build `hello', so when `configure' creates `src/Makefile' from
`src/Makefile.in' it will define `CC' with the value it has found.  If
Automake is asked to create a `Makefile.in' that uses `CC' but
`configure.ac' does not define it, it will suggest you add a call to
`AC_PROG_CC'.

   The `AC_CONFIG_HEADERS([config.h])' invocation causes the
`configure' script to create a `config.h' file gathering `#define's
defined by other macros in `configure.ac'.  In our case, the `AC_INIT'
macro already defined a few of them.  Here is an excerpt of `config.h'
after `configure' has run:

     ...
     /* Define to the address where bug reports for this package should be 
sent. */
     #define PACKAGE_BUGREPORT "address@hidden"

     /* Define to the full name and version of this package. */
     #define PACKAGE_STRING "amhello 1.0"
     ...

   As you probably noticed, `src/main.c' includes `config.h' so it can
use `PACKAGE_STRING'.  In a real work project, `config.h' can grow
really big, with one `#define' per feature probed on the system.

   The `AC_CONFIG_FILES' macro declares the list of files that
`configure' should create from their `*.in' template.  Automake also
scans this list to find the `Makefile.am' it must process.  (This is
important to remember: when adding a new directory to your project, you
should add its `Makefile' to this list, otherwise Automake will never
process the new `Makefile.am' you wrote in that directory.)

   Finally the `AC_OUTPUT' line is a closing command that actually
produces the part of the script in charge of creating the files
registered with `AC_CONFIG_HEADERS' and `AC_CONFIG_FILES'.

   When starting a new project, we suggest you start with such a simple
`configure.ac', and gradually add the other tests it requires.  The
command `autoscan' can also suggest of few of the tests your package
may need (*note Using `autoscan' to Create `configure.ac':
(autoconf)autoscan Invocation.).

   We now turn to `src/Makefile.am'.  This file contains Automake
instructions to build and install `hello'.

     bin_PROGRAMS = hello
     hello_SOURCES = main.c

   A `Makefile.am' has the same syntax as an ordinary `Makefile'.  When
`automake' processes a `Makefile.am' it copies the entire file into the
output `Makefile.in' (that will be later turned into `Makefile' by
`configure') but will react to certain variable definitions by
generating some build rules and other variables.  Often `Makefile.am's
contain only a list variable definitions as above, but it can also
contains other variable and rule definitions that `automake' will pass
along without interpretation.

   Variables that ends with `_PROGRAMS' are special variables that list
programs that the resulting `Makefile' should build.  In Automake
speak, this `_PROGRAMS' suffix is called a "primary"; Automake
recognises other primaries such as `_SCRIPTS', `_DATA', `_LIBRARIES',
etc. corresponding to different type of files.

   The `bin' part of the `bin_PROGRAMS' tells `automake' that the
resulting programs should be installed in BINDIR.  Recall that the GNU
Build System uses a set of variables to denote destination directories
and allow users to customise these locations (*note Standard Directory
Variables::).  Any such directory variable can be put in front of a
primary (omitting the `dir' suffix) to tell `automake' where to install
the listed files.

   Programs need to be built from source files, so for each program
`PROG' listed in a `_PROGRAMS' variable, `automake' will look for
another variable named `PROG_SOURCES' listing its source files.  There
may be more that one source file: they will all be compiled and linked
together.

   Automake also knows that source files need to be distributed when
creating a tarball (unlike built programs).  So a side-effect of this
`hello_SOURCES' declaration is that `main.c' will be part of the
tarball created by `make dist'.

   Finally here are some explanations regarding the top-level
`Makefile.am'.

     SUBDIRS = src
     dist_doc_DATA = README

   `SUBDIRS' is a special variable listing all directories that `make'
should recurse into before processing the current directory.  So this
line is responsible for `make' building `src/hello' even though we run
it from the top-level.  This line also causes `make install' to install
`src/hello' before installing `README' (not that this order matters).

   The line `dist_doc_DATA = README' causes `README' to be distributed
and installed in DOCDIR.  Files listed with the `_DATA' primary are not
automatically part of the tarball built with `make dist', so we add the
`dist_' prefix so they get distributed.  However for `README' it
wouldn't have been necessary: `automake' automatically distribute any
`README' file it encounters (the list of other files automatically
distributed is presented by `automake --help').  The only important
effect of this second line is therefore to install `README' during
`make install'.

-- 
Alexandre Duret-Lutz

Shared books are happy books.     http://www.bookcrossing.com/friend/gadl





reply via email to

[Prev in Thread] Current Thread [Next in Thread]