In Section 3.1 we saw the work that a tiny two-line, seemingly
do-nothing configure.in macro script can do when run through
the autoconf tool. In this section we'll see more of the power
of autoconf unleashed. The autoconf package is distributed
with a huge collection of macros, each of which is prefixed
with "AC_". These macros expand into shell script code in the
configure file, capable of searching the target system for
compilers, external libraries, include files, and even
specific functions inside libraries and include files. You can
place these macros with their respective parameters in
configure.in or even write your own macros from scratch if the
standard macros won't do the job. It all ends up as a shell
script, so your only limitations are what the shell can do.

The autoconf system is the gatekeeper of all your
configuration needs. As the name suggests, autoconf performs
automated configuration. The interesting thing about
autoconf is that it runs on the developer's machine but
doesn't do its real magic until its generated scripts run on
the end user's machine. It's like a time-released depth
charge.

This setup solves many problems for the developer. Most
importantly, it reduces the number of software dependencies
that the system administrator needs when installing the
software. The developer must have autoconf, automake, and
possibly libtool on the development machine, but the output
of these tools consists for the most part of generic shell
scripts. Thus to compile and install software that has been
processed by autoconf, all you need is a command line shell
(available on every flavor of UNIX in existence), a
compiler, and a recent enough version of make.

The configure.in script should always start with the AC_INIT
macro and always end with the AC_OUTPUT macro. AC_INIT
processes any command line options you might have given
while running configure; it also double-checks the compile
directory to make sure your build environment is in good
shape. If the file you supply as a parameter to AC_INIT does
not exist in the source tree, the generated configure script
will bail out with an error message. You should always try
to use a uniquely named source file for this check so that
configure can quickly detect a dubious compilation environ-
ment.

The autoconf system handles automatic file generation with
the AC_OUTPUT macro. You supply a space-delimited list of
target files you want the configure script to create;
configure then searches for a file in the same path with
".in" appended to it and uses that as a template for
creating the final output file. Thus if you wanted to
perform variable substitutions on a shell script template
init-app.sh.in in the root of the source tree, and on a
Makefile.in in the src subdirectory, you would use the
following command:

As we saw in the previous section, you can pass a value
directly to your makefiles with AC_SUBST. This macro will
cause autoconf to insert the variable's value into the text
of the makefile. You can then use it however you need to in
the makefile, including passing it on to the compiler as
part of its command line string.

However, if all you want to do is define some values for
your code with #define, autoconf has a special macro for the job,
AC_DEFINE. Normally autoconf places these values, formatted for your
compile line, into a globally available makefile variable,
DEFS. Internally, autoconf calls AC_SUBST(DEFS) to imprint it in your
makefiles, so you will still need to put a @DEFS@ declaration
somewhere in your Makefile.in file in order to use it (unless you use
automake, as described in Section 3.3.2). The prototype for AC_DEFINE
looks like this:

AC_DEFINE (VARIABLE [, VALUE [, DESCRIPTION]])

The VARIABLE parameter gives autoconf the name of the C
constant to define; VARIABLE is the only required
parameter. VALUE allows you to specify the contents of
VARIABLE and defaults to 1 if you omit it. The DESCRIPTION
parameter lets you specify a descriptive comment for the
#define statement, but it is used only in conjunction with
the AC_CONFIG_HEADER macro, as we'll see in a moment.

Try adding the following lines to configure.in somewhere
between AC_INIT and AC_OUTPUT:

AC_DEFINE(USE_FOO)
AC_DEFINE(APPNAME, "myapp")

Then add this line anywhere in Makefile.in:

MYDEFS = @DEFS@

Run autoconf again-because we've modified configure.in-and
then run the freshly created configure script to regenerate
the makefile. The makefile has gained the line

MYDEFS = -DUSE_FOO=1 -DAPPNAME=\"myapp\"

The autoconf script added the compiler-specific -D options
for us and even took the opportunity to tack on "=1" as a
default value to the USE_FOO definition. Unlike AC_SUBST,
which puts each declaration into a separate variable, all
invocations to AC_DEFINE will concatenate their arguments
onto the end of the DEFS variable. If you tried to do this
with AC_SUBST, you would end up with code like this in the
Makefile.in file:

MYDEFS = "-DUSE_FOO=@USE_FOO@ -DAPPNAME=@APPNAME@"

A couple of these substitutions aren't too bad, but once you
get into a larger, more complex project with 10 or 20 (or
more!) declared variables, you'll be glad that you don't
have to maintain this all by hand. You just call AC_DEFINE
on each one as you go, and autoconf takes care of the rest.

This brings up a small problem with using AC_DEFINE and
DEFS: scalability. If you have 10 -D options in every
command line, your compile outputs will become voluminous
and hard to read. The important stuff will become lost in a
sea of compile parameters. To deal with this situation,
autoconf has an alternate mode of handling AC_DEFINE that is
much more scalable than using DEFS. autoconf can place all
your AC_DEFINE declarations into a header file, which you
can then add to your source files with the #include
directive. You announce which header file you want to use
with the AC_CONFIG_HEADER macro. You'll typically want to
call this macro right after AC_INIT, as the second macro
in your configure.in file.

Of course, it's not quite as easy as all that. autoconf also
needs a template file to tell it how to format the
configuration header. The configuration header file is
usually named config.h, and the template file is usually the
configuration file with the familiar ".in" suffix,
config.h.in. As far as autoconf is concerned, it is
entirely your job to create this header file, although the
autoconf distribution comes with a little tool, autoheader,
that automatically generates a config.h.in file for you on
the basis of the contents of your configure.in file.

The config.h.in file looks like any normal C header file,
except it contains only comments and #define statements,
according to what you passed into the AC_DEFINE macro (this
is where the DESCRIPTION parameter comes into play). All of
these #define statements must either set the value to 0 or
undefine it completely with #undef. autoconf uses the
config.h.in file as a checklist for the various tests it
runs. Each time it hits an AC_DEFINE macro, it searches the
config.h.in file for a matching #define statement,
uncomments it, and sets the value to 1.

As a final step, autoconf puts the value -DHAVE_CONFIG_H
into the DEFS variable. You'll still want to pass the value
of DEFS to the compiler in your makefile (as @DEFS@ in
Makefile.in), and then check for the HAVE_CONFIG_H macro in
your source code. At the top of your source files you can do
something like this:

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

As we'll see in Section 3.3, automake helps make this process
even easier.

The autoconf package comes bundled with an exhaustive set of
macros for probing target systems. Autoconf makes use of m4,
a commonly available macro-processing program. As part of
its own distribution, autoconf supplies numerous text files
(all of which end in ".m4"), full of various m4 macros. The
m4 macro language looks a little odd at first, but it can be
very powerful when used correctly.

As we've seen, autoconf expands these macros into shell
commands in the configure script. Many people use m4 to
create text files and perform a wide variety of other
tasks. For example, GTK--, a C++ wrapper around GTK+, uses
m4 to automate the creation of a great deal of repetitive
source code. The UNIX e-mail transport utility sendmail uses
m4 to generate its complex configuration files from an
easy-to-read template. m4 is a generic tool with many uses.

You can tap into this power by adding the m4 macros
distributed with autoconf to your configure.in file. The
configure.in file is in fact a mixture of m4 macros and
inline shell script code. In addition to the initialization
and variable-passing macros we saw in the previous
section, autoconf comes with a broad selection of macros for
probing standard UNIX tools. They typically don't require
parameters. You just add each macro on its own line, without
parentheses. If one of the prepackaged macros doesn't do
what you want, you can write your own custom macro. Here are
some common tool macros, exactly as they would appear in a
configure.in file:

Each one checks for the existence of a tool or program,
first by seeing if it is explicitly named by the user in an
environment variable, and if not, by searching the hard
drive for it (i.e., the hard way). For example, AC_PROG_CC
first checks to see if the CC environment variable is set on
the end user's system. If it is, the configure script adds
the contents of CC to the master list of variable
substitutions. You can then reference @CC@ in your
Makefile.in files, just like the other AC_SUBST
variables. If the user hasn't explicitly set the environment
variable CC, AC_PROG_CC will search the directories in the
PATH environment variable for the gcc or cc executables. If
it finds something, it will call AC_SUBST on that value
instead. This makes it very easy for the user to override
the default compiler before configuring a software package
that has been processed by autoconf. If the configure
script fails to find any trace of a compiler, it aborts
the configuration process with an error message.

The other AC_PROG_* macros work similarly. See the autoconf
documentation for an explanation of each one. If you're
feeling adventurous, you can explore autoconf's m4 files to
find out what's really going on. You can find these files in
the autoconf install directory, usually something like
/usr/share/autoconf or /usr/lib/autoconf, depending on your
distribution of UNIX or Linux. You may also want to
consult the m4 documentation. If you plan on someday writing
your own macros, this will be time well spent.

A frequent problem with porting software is keeping track of
header files. Different systems have headers in different
places. If your software depends on other libraries, it
should attempt to verify that those libraries and their
accompanying header files are installed before continuing
with the compilation of your package. For example, if you're
compiling a GNOME application, you'll want to make sure the
header files for the gnome-libs package are available.

AC_CHECK_HEADER allows you to check for specific header
files. You supply the name of the header file, plus an
optional command if the header is found and another optional
command if the header is not found.

Here's an example that aborts the configure process if the
header file grump.h isn't found. The autoconf system uses
the square brackets-[ and ]- as the default quote characters
for its m4 macros, rather than the double quotation mark
("), to make it easier to include double quotation marks in
your macros. The AC_MSG_ERROR macro that follows prints
out a message and then aborts the configure process. If you
just want to print out a nonfatal warning or status message
and then keep going, you can use the AC_MSG_RESULT macro
instead.

Several things can cause this check to fail. The header file
must first exist; the user must also have permission to read
it. To perform the check, the configure script creates a
very simple C program that consists more or less of a single
#include statement for the supplied header file, in our case
grump.h. The configure script then tries to compile it,
adding the contents of the CPPFLAGS environment variable to
the compile line. Whoever is compiling the software will
have to add any include paths to CPPFLAGS that aren't
implicitly checked by the compiler. If the header files are
installed in a nonstandard location, such as /opt/include,
and CPPFLAGS doesn't refer to that directory-for example, as
-I/opt/include-the AC_CHECK_HEADER macro will fail, even
though the files do exist on the system. However, this is an
issue for the system's administrator. Part of the
convenience of autoconf is that you, as the developer,
don't need to worry about these details.

If you have a lot of header files to check for, or only want
to find one out of a list of multiple header files, you can
use AC_CHECK_HEADERS. The format for AC_CHECK_HEADERS is the
same as with AC_CHECK_HEADER, except that you can list
multiple files, separated by spaces, in the first
parameter. The following example will search for three
header files. It will call AC_DEFINE to add a #define
statement to config.h (or DEFS) for the first one it
finds. If it doesn't find any of them, it will produce an
error message and bail out of the configure script.

If configure finds grump-linux.h, it will create a #define
statement for HAVE_GRUMP_LINUX_H and so on, which you can
check for in your code. If you want to check for all the
listed header files, simply omit the break command.

Each program check will set an environment variable,
VARIABLE, with AC_SUBST, according to whether the program is
found (VALUE-IF-FOUND) or not
(VALUE-IF-NOT-FOUND). PROG-TO-CHECK-FOR is the file name of
the program. You can use the optional parameter PATH to
override the PATH environment variable, and REJECT to ignore
specific path-program combinations-for example, if you
know that more than one program has the same name, blahblah,
and that the version you don't want is always at
/usr/bin/blahblah.

The AC_CHECK_PROGS macro does pretty much the same thing,
except you can provide a list of programs to search
for. AC_CHECK_PROGS places the first program it finds into
VARIABLE. Here's an example that checks for the fictitious
program zed.

First it looks for zed in the normal PATH-first as zed, then
as zed2000 and zed-x11. If it finds any of these versions of
zed, it sets the ZED variable to that value and uses
AC_SUBST to substitute it into the makefile. In the second
macro it checks for the existence of zed-x11 and sets the
USE_ZED_X11 environment variable to yes if it does find it
and no if it doesn't. The result is that $(ZED) will be set
to whichever version of zed the user has installed, but if
the user happens to have zed-x11 installed, extra support
for the X11 version can be conditionally compiled on the
target system, according to the value of $USE_ZED_X11. Note
that nothing magic happens in your code because of an
autoconf macro. You still have to check for the USE_ZED_X11
in the makefile and add the proper conditional blocks to
enable or disable the extra support. In Section 3.3.4 we'll
see how to do this with the AM_CONDITIONAL macro.

When checking for libraries, you give the name of the
library and an important function name within that
library. By allowing you to name a specific function to
search for, autoconf lets you check for specific
functionality in a library. Often many similar
implementations are floating around for the same li-
brary. A good example is the standard C library. On
different platforms, libc may or may not contain certain
common functions, like vsnprintf( ) and strcasecmp( ). The
version number of the library isn't much help because
there's no universal correspondence between the version
number and the functions a library contains. Version 2.1 of
libc on platform A might have vsnprintf( ), while version
5.0 of libc on platform B might not. Version number checks
would quickly deteriorate into a swampy maze of special
cases, and they require intricate knowledge of the histories
of each platform. It's so much easier just to check for the
function directly.

The AC_CHECK_LIB macro uses a technique similar to that of
AC_CHECK_HEADER. AC_CHECK_LIB creates and compiles a simple
temporary program that calls the function, passing the
library in on the link line. If the program compiles
successfully, AC_CHECK_LIB knows that the function exists in
that library. If compilation fails, it knows that the
function doesn't exist there, even though it might be
somewhere else on the system. It's possible to nest
successive calls to AC_CHECK_LIB, so you can specify
alternate libraries to search for the function if the first
try fails (stay tuned for more on that feature).

LIBRARY is the base name of the library; if you were
checking for libgrump.so, you would pass in grump. The
following macro would check for the grump_some( ) function
in libgrump.so or libgrump.a:

AC_CHECK_LIB(grump, grump_some)

The default action is to add the library to the LIBS
variable and create a special #define statement for it with
AC_DEFINE. In our grump example, AC_CHECK_LIB would add
-lgrump to LIBS and the #define statement HAVE_LIBGRUMP to
config.h if it found libgrump.so or libgrump.a. If the li-
brary you're searching has additional library dependencies,
you may have to add those as the OTHER-LIBRARIES
parameter. If libgrump.so required libcrypt, you would do
this instead:

AC_CHECK_LIB(grump, grump_some, , , -lcrypt)

AC_CHECK_LIB will automatically create the #define
HAVE_LIBxxx statement for you to use in your source code,
but if you need to perform any special custom actions at
configure time, you can add shell script code or other m4
macros to the ACTION-IF-FOUND and ACTION-IF-NOT-FOUND
parameters. The NOT-FOUND parameter is a good place to
perform nested library checks. In our example, if the
grump_some( ) function were instead located in the
libgrumpus library on certain platforms, you could invoke a
fallback check for it like this:

If you need a specific function and don't care which library
it resides in, you can check for it with the AC_CHECK_FUNCS
macro. Simply provide a list of function names, and for each
one it finds, AC_CHECK_FUNCS will define HAVE_FUNCTION.

Figuring out which macros to include in your configure.in
file can be a Herculean task. Without broad experience in
porting and cross-compiling, you'll probably end up guessing
which functions and libraries you need to test for. Do all
platforms have native support for inline functions? Should
you bother checking for vsnprintf( )? Who knows?

The autoconf package has a helper utility called autoscan
that snoops through your source files looking for common
portability problems. It generates a fully formed-but
typically quite lean-configure.in file for you. By default
it saves this file as configure.scan. You'll still have to
do some work to customize the configure.scan file.

Another helpful tool is ifnames, a utility to extract and
sort all the preprocessor define statements in your source
files. You invoke ifnames with a list of file names (you can
also pipe the files to ifnames through stdin), and it spits
back a sorted list of all the #if, #ifdef, #elif, and
#ifndef statements it finds. This is especially useful if
you are adding autoconf support to an existing software
package.

If you are using a config.h file, you may want to try out
the autoheader tool. autoheader automatically creates the
config.h.in file for you on the basis of the macros you
call in configure.in. In particular, autoheader looks for
any calls to AC_DEFINE, plus any HAVE_* definitions created
by the AC_CHECK_* macros. These preprocessor statements must
be undefined (by #undef) in a file called acconfig.h (unless
you specify the value in the optional second parameter to
AC_DEFINE). The undefinitions are inserted into config.h to
protect autoconf's declarations from declarations that might
coincidentally occur in external header files. Autoconf
comes with an acconfig.h of its own that supplies most of
the common #undef statements you'll need. If you create new
ones, you have to add them to a new acconfig.h file in your
source directory. autoheader combines both of these when it
creates config.h.in. This tool can save you quite a lot of
work in a large project.