Next Up Previous Contents
Next: 2.1.2 Automake
Up: 2.1 Overview of the Autotools
Previous: 2.1 Overview of the Autotools
[ID index][Keyword index]

2.1.1 Autoconf

We use a slightly extended version of autoconf. See autoconf --version for the base version number.

The goal of autoconf is to help you make your program portable, by allowing you, at build time, to adapt the program to the facilities available on the machine on which the program is being built.

You control this through a script called configure.ac (which was called configure.in in older versions of autoconf). The autoconf program produces from this a very portable /bin/sh script called configure, which is distributed as part of your package, and which the person building the package runs as the first part of the ./configure; make; make install incantation.

The ./configure script probes the system it is running on, finding compilers, testing the behaviour of the local unix system, testing whether specific include files exist or not, testing whether required functions are available and working as expected, and managing some configuration by the user, such as allowing them to specify where the package is to be installed.

This information is only useful if it can be communicated to your program in some way. This is done by the configure script by editing the values of certain `substitution variables' into a list of template files.

For example, you might have a version header file version.h.in, containing the line


const char version[] = "@PACKAGE_VERSION@";
The configure variable PACKAGE_VERSION is one of those substituted by default, and if this file were listed as one of those to be substituted (by mentioning it in the autoconf macro AC_CONFIG_FILES(version.h)), then a file version.h would be created containing the contents of the version.h.in file with the @PACKAGE_VERSION@ substituted by the version number declared within the configure file.

Although this substitution process can be done for any template file, there are two template files which are used particularly often.

The first is Makefile.in, which is a skeleton makefile which you might write by hand (though see the discussion of automake in Section 2.1.2). There is an example of this at the top level of the Starlink build tree. A typical Makefile.in might include lines like


LN_S = @LN_S@
CC = @CC@
myfile.o: myfile.c
        $(CC) -o myfile.o myfile.c
That, combined with autoconf macros AC_PROG_CC and AC_PROG_LN_S, would allow you to produce a file Makefile which was customised to use the C compiler appropriate to the local environment, and which had, in the makefile variable $(LN_S) a command which makes links between files if the local platform supports that, or makes hard links or simple copies if that is all that is possible.

As well as configuring the makefile, you may also want to configure the source code, so that you can take different actions in your code depending on whether certain functions or headers are available. That is is most often done via a particular configured file, conventionally named config.h. This second way of communicating with your source code has the config.h file substituted with a number of C preprocessor #define statements. For example, if you included in your configure.ac file the lines


AC_CHECK_HEADERS([sys/wait.h])
AC_CHECK_FUNCS([strchr])
then the configure script generated from that source would include a test of whether the sys/wait.h header file was available, and whether the strchr function was available in the C library. If so, the resulting config.h file would include the lines

#define HAVE_SYS_WAIT_H 1
#define HAVE_STRCHR 1
Whereas most configured files are substituted as a result of being mentioned in a AC_CONFIG_FILES() macro, the config.h.in input file is configured through AC_CONFIG_HEADERS(config.h), which does its configuration in a slightly different way.

After including this file into your source code with


#include <config.h>
you can adjust the compiled code with suitable #if preprocessor conditionals, such as

#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif

It is possible to maintain the config.h.in file by hand, but generally better to generate it by using the autoheader application which is part of autoconf. This scans your configure.ac and extracts into config.h.in mentions of all those preprocessor defines it finds. Autoheader knows about macros such as AC_CHECK_HEADERS above; if you wish to add further switches to the config.h.in file, you should do so by calling the autoconf macro AC_DEFINE. See the section 7.1 Defining C Preprocessor Symbols in the autoconf manual for further details. Autoheader is one of those applications run on your behalf by autoreconf (see Section 2.1.4).

Note the angle brackets round config.h: this is preferred to double quotes, as it gives the makefile the option of controlling where the source code is; in the simplest case this is handed by simply adding -I. to the compile line. We don't take take advantage of this particular flexibility, but it is a good habit to get into.

An illustrative configure.ac might look like this (with line numbers inserted):


1   AC_INIT(mypack, 1.2, ussc@star.rl.ac.uk)
2   AC_CONFIG_SRCDIR(src.c)
3   STAR_DEFAULTS
4   AC_PROG_CC
5   AC_PATH_PROG(PERL, perl)
6   AC_CHECK_HEADERS([sys/time.h])
7   STAR_MESSGEN(mypack_err.msg)
8   AC_CONFIG_HEADERS(config.h)
9   AC_CONFIG_FILES(Makefile)
10  AC_CONFIG_FILES(myscript.pl, [chmod +x myscript.pl])
11  AC_OUTPUT

Line 1: This line is required. It declares the package name, version number, and bug-report address. Each of these is available for substitution via the substitution variables PACKAGE_NAME, PACKAGE_VERSION and PACKAGE_BUGREPORT. See autoconf 4.1 Initializing configure

Line 2: This is largely a sanity check, and produces an error if the named file (in this case src.c) is not in the source directory. The source directory is typically the current directory, but you can specify a different one using the --srcdir option to ./configure, if you have a good reason for doing that. See autoconf 4.3 Finding configure Input

Line 3: This macro is one of the Starlink extensions, and the only required Starlink macro. It sets up the defaults required for building Starlink applications, and assures the starconf program that it's being run in the correct directory. See Section 2.2 for a description of the starconf application, and Appendix A for details of the associated macros.

Line 4: This finds a working C compiler, and prepares to substitute it in the substitution variable CC. Presumably the Makefile.in has a line CC=@CC@. See autoconf 5.10.3 C Compiler Characteristics

Line 5: Find a binary called perl in the current PATH and assign the substitution variable PERL the full path to it. The most common way of using this would be for the file myscript.pl.in to start off with the line


#! @PERL@ -w
so that the script ends up with the correct full path. See line 10 and autoconf 5.2.2 Generic Program and File Checks.

Line 6: check that the system has an include file sys/time.h in the include path, and if it has, make sure that the cpp variable HAVE_SYS_TIME_H is defined. If this were a real configure file, you would likely have several other header tests here (in a space-separated list, surrounded by square brackets), and cpp branching inside your source code to handle the various cases. See line 8 and autoconf 5.6.3 Generic Header Checks.

Line 7: Another Starlink extension. It declares that this package has a set of ERR messages in the given file, and that autoconf should check the location of the messgen application. The argument is in fact optional (it merely causes the files to be declared as pre-distribution files -- see Appendix A.26); this line should be partnered by a declaration of the variable include_MESSAGES in the corresponding Makefile.am. See Appendix A.22 for fuller details.

Line 8: This is the macro that makes cpp configuration information available, by editing the header file config.h.in (this file name is conventional, but not required). See autoconf 4.8 Configuration Header Files. If you want to put extra information into this file, use the AC_DEFINE macro: a declaration like AC_DEFINE(SPECIALCASE,1) would insert #define SPECIALCASE 1 into the config.h; autoheader also spots this and puts a suitable template into config.h.in. See the autoconf manual, section Defining C preprocessor symbols, for further details.

Line 9: This does the work of substituting the results of the various tests into the files being configured. For each of the files named in the (space-separated list) argument, which most typically includes Makefile, autoconf expects to find a file of the same name but with .in appended, and this is the file which has the substitutions edited in. (Automake also looks at this line, and if it sees a Makefile mentioned here, it looks to see if there is a corresponding Makefile.am already present, and if so, recurses)

Line 10: This is a variant of line 9. The AC_CONFIG_FILES macro takes a second argument consisting of one or more lines of shell script to post-process the file in question, in this case making sure that the generated file is executable.

Line 11: This is the line which really does the work. See 4.4 Outputting Files.

Of this script, it is lines 1, 2 and 11 which are absolutely required, along with something like line 9 to make the configure script do something useful.

It is useful to think of the configure.ac file as being the template for the final ./configure script, with the autoconf macros simply expanding to (large chunks of) shell script during translation by the autoconf program. This isn't the whole truth, but it suffices for almost all purposes. About the only place where this view might deceive you is if you wished to modify a file after it was generated by AC_CONFIG_FILES for example; if you did that immediately after the AC_CONFIG_FILES line it would fail, since the code which generates the files is in a different place from the AC_CONFIG_FILES line -- that is why AC_CONFIG_FILES has its second argument. With this view it is natural that you can add any other shell scripting to your configure.ac, adding any tests and switches you fancy. You communicate the results of your scripting to the output files by making shell variables into substitution variables, and the way you do that is by calling AC_SUBST on them. Thus, after


wibble=''
... # lots of clever scripting
AC_SUBST(wibble)
any occurrences of the string @wibble@ in the substituted files will be replaced by the value of wibble at the end of the ./configure script.

2.1.1.1 M4 syntax and traps

Autoconf does its work by running the configure.ac file through the text processor GNU m4, and this can cause occasional surprises.

M4 is a macro language, intended for very much the sort of rewriting that autoconf does. When m4 processes a file, anything at all that looks like an m4 macro is substituted, so that there is no macro invocation character like the backslash in TeX. Macros can take arguments, delimited by round brackets and separated by commas, as illustrated above.

The first oddity is to do with comment characters. The default m4 comment character is #, but since this is also the shell script and makefile comment character, autoconf makes it an ordinary character. Thus to add comments to a configure.ac file which won't make it into the ./configure file, you should prefix them with the m4 macro dnl (which means `delete to next newline'), as in


dnl   This is a comment
AC_INIT(...)
There's no harm in including #-style comments in your configure.ac file and allowing these to be passed through to the output file, since `got-here' type comments can sometimes help you debug the ./configure script.

The default m4 quote characters are the left and right single quotes, but autoconf changes these to left and right square brackets. You need to use these in two circumstances, firstly when you have a multi-word argument to a macro, and particularly when that argument contains a comma, and secondly if a piece of text looks like a current m4 macro. In general, if you need to care about m4 quoting rules, you're in trouble, but see section 8.1 M4 Quotation in the autoconf manual, for some advice.


Next Up Previous Contents
Next: 2.1.2 Automake
Up: 2.1 Overview of the Autotools
Previous: 2.1 Overview of the Autotools
[ID index][Keyword index]
The Starlink Build System
Starlink System Note 78
Norman Gray, Peter W Draper, Mark B Taylor, Steven E Rankin
11 April 2005. Release snapshot: $Revision: 1.116 $. Last updated 28 May 2006