|  |  12.3 Installing Header Files 
 
One of the more difficult problems with GNU Autotools driven projects is
that each of them depends on `config.h' (or its equivalent) and the
project specific symbols that it defines.  The purpose of this file is
to be #included from all of the project source files.  The
preprocessor can tailor then the code in these files to the target
environment.
It is often difficult and sometimes impossible to not introduce a
dependency on `config.h' from one of the project's installable
header files. It would be nice if you could simply install the generated
`config.h', but even if you name it carefully or install it to a
subdirectory to avoid filename problems, the macros it defines will
clash with those from any other GNU Autotools based project which also
installs its `config.h'.
 
For example, if Sic installed its `config.h' as
`/usr/include/sic/config.h', and had `#include <sic/config.h>'
in the installed `common.h', when another GNU Autotools based project
came to use the Sic library it might begin like this:
 
 |  | 
 #if HAVE_CONFIG_H
#  include <config.h>
#endif
#if HAVE_SIC_H
#  include <sic.h>
#endif
static const char version_number[] = VERSION;
 | 
 
But, `sic.h' says `#include <sic/common.h>', which in turn
says `#include <sic/config.h>'.  Even though the other project has
the correct value for `VERSION' in its own `config.h', by the
time the preprocessor reaches the `version_number' definition, it
has been redefined to the value in `sic/config.h'.  Imagine the
mess you could get into if you were using several libraries which each
installed their own `config.h' definitions.  GCC issues a
warning when a macro is redefined to a different value which would help
you to catch this error.  Some compilers do not issue a warning, and
perhaps worse, other compilers will warn even if the repeated
definitions have the same value, flooding you with hundreds of warnings
for each source file that reads multiple `config.h' headers.
 
The Autoconf macro AC_OUTPUT_COMMANDS(25) provides a way to solve this problem.  The
idea is to generate a system specific but installable header from the
results of the various tests performed byconfigure.  There is
a 1-to-1 mapping between the preprocessor code that relied on the
configure results written to `config.h', and the new shell code
that relies on the configure results saved in `config.cache'. 
 
The following code is a snippet from `configure.in', in the body of
the AC_OUTPUT_COMMANDSmacro: 
 |  | 
     # Add the code to include these headers only if autoconf has
    # shown them to be present.
    if test x$ac_cv_header_stdlib_h = xyes; then
      echo '#include <stdlib.h>' >> $tmpfile
    fi
    if test x$ac_cv_header_unistd_h = xyes; then
      echo '#include <unistd.h>' >> $tmpfile
    fi
    if test x$ac_cv_header_sys_wait_h = xyes; then
      echo '#include <sys/wait.h>' >> $tmpfile
    fi
    if test x$ac_cv_header_errno_h = xyes; then
      echo '#include <errno.h>' >> $tmpfile
    fi
    cat >> $tmpfile << '_EOF_'
#ifndef errno
/* Some sytems #define this! */
extern int errno;
#endif
_EOF_
    if test x$ac_cv_header_string_h = xyes; then
      echo '#include <string.h>' >> $tmpfile
    elif test x$ac_cv_header_strings_h = xyes; then
      echo '#include <strings.h>' >> $tmpfile
    fi
    if test x$ac_cv_header_assert_h = xyes; then
      cat >> $tmpfile << '_EOF_'
#include <assert.h>
#define SIC_ASSERT assert
_EOF_
    else
        echo '#define SIC_ASSERT(expr)  ((void) 0)' >> $tmpfile
    fi
 | 
 
Compare this with the equivalent C pre-processor code from
`sic/common.h', which it replaces:
 
 |  | 
 #if STDC_HEADERS || HAVE_STDLIB_H
#  include <stdlib.h>
#endif
#if HAVE_UNISTD_H
#  include <unistd.h>
#endif
#if HAVE_SYS_WAIT_H
#  include <sys/wait.h>
#endif
#if HAVE_ERRNO_H
#  include <errno.h>
#endif
#ifndef errno
/* Some systems #define this! */
extern int errno;
#endif
#if HAVE_STRING_H
#  include <string.h>
#else
#  if HAVE_STRING_H
#    include <strings.h>
#  endif
#endif
#if HAVE_ASSERT_H
#  include <assert.h>
#  define SIC_ASSERT assert
#else
#  define SIC_ASSERT(expr) ((void) 0)
#endif
 | 
 
Apart from the mechanical process of translating the preprocessor code,
there is some plumbing needed to ensure that the `common.h' file
generated by the new code in `configure.in' is functionally
equivalent to the old code, and is generated in a correct and timely
fashion.
 
Taking my lead from some of the Automake generated makerules
to regenerate `Makefile' from `Makefile.in' by calling
`config.status', I have added some similar rules to
`sic/Makefile.am' to regenerate `common.h' from
`common-h.in'. 
 |  | 
 # Regenerate common.h with config.status whenever common-h.in changes.
common.h: stamp-common
        @:
stamp-common: $(srcdir)/common-h.in $(top_builddir)/config.status
        cd $(top_builddir) \
          && CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=sic/common.h \
          $(SHELL) ./config.status
        echo timestamp > $@
 | 
 
The way that AC_OUTPUT_COMMANDSworks, is to copy the contained
code intoconfig.status(see section C. Generated File Dependencies).  It is actuallyconfig.statusthat creates the
generated files -- for example,automakegenerated`Makefile's are able to regenerate themselves from corresponding
`Makefile.in's by calling
 config.statusif they become
out of date.  Unfortunately, this means thatconfig.statusdoesn't have direct access to the cache values generated whileconfigurewas running (because it has finished its work by the
timeconfig.statusis called).  It is tempting to read in the
cache file at the top of the code insideAC_OUTPUT_COMMANDS, but
that only works if you know where the cache file is saved.  Also the
package installer can use the `--cache-file' option ofconfigureto change the location of the file, or turn off
caching entirely with `--cache-file=/dev/null'. 
AC_OUTPUT_COMMANDSaccepts a second argument which can be used
to pass the variable settings discovered byconfigureintoconfig.status.  It's not pretty, and is a little error prone.
In the first argument toAC_OUTPUT_COMMANDS, you must be careful
to check that every single configure variable referenced is
correctly set somewhere in the second argument. 
A slightly stripped down example from the sic project
`configure.in' looks like this:
 
 |  | 
 # ----------------------------------------------------------------------
# Add code to config.status to create an installable host dependent
# configuration file.
# ----------------------------------------------------------------------
AC_OUTPUT_COMMANDS([
  if test -n "$CONFIG_FILES" && test -n "$CONFIG_HEADERS"; then
    # If both these vars are non-empty, then config.status wasn't run by
    # automake rules (which always set one or the other to empty).
    CONFIG_OTHER=${CONFIG_OTHER-sic/common.h}
  fi
  case "$CONFIG_OTHER" in
  *sic/common.h*)
    outfile=sic/common.h
    stampfile=sic/stamp-common
    tmpfile=${outfile}T
    dirname="sed s,^.*/,,g"
    echo creating $outfile
    cat > $tmpfile << _EOF_
/*  -*- Mode: C -*-
 * --------------------------------------------------------------------
 * DO NOT EDIT THIS FILE!  It has been automatically generated
 * from:    configure.in and `echo $outfile|$dirname`.in
 * on host: `(hostname || uname -n) 2>/dev/null | sed 1q`
 * --------------------------------------------------------------------
 */
#ifndef SIC_COMMON_H
#define SIC_COMMON_H 1
#include <stdio.h>
#include <sys/types.h>
_EOF_
    if test x$ac_cv_func_bzero = xno && \
       test x$ac_cv_func_memset = xyes; then
      cat >> $tmpfile << '_EOF_'
#define bzero(buf, bytes) ((void) memset (buf, 0, bytes))
_EOF_
    fi
    if test x$ac_cv_func_strchr = xno; then
      echo '#define strchr index' >> $tmpfile
    fi
    if test x$ac_cv_func_strrchr = xno; then
      echo '#define strrchr rindex' >> $tmpfile
    fi
    # The ugly but portable cpp stuff comes from here
    infile=$srcdir/sic/`echo $outfile | sed 's,.*/,,g;s,\..*$,,g'`-h.in
    sed '/^##.*$/d' $infile >> $tmpfile 
],[
  srcdir=$srcdir
  ac_cv_func_bzero=$ac_cv_func_bzero
  ac_cv_func_memset=$ac_cv_func_memset
  ac_cv_func_strchr=$ac_cv_func_strchr
  ac_cv_func_strrchr=$ac_cv_func_strrchr
])
 | 
 
You will notice that the contents of `common-h.in' are copied into
`common.h' verbatim as it is generated.  It's just an easy way of
collecting together the code that belongs in `common.h', but which
doesn't rely on configuration tests, without cluttering
`configure.in' any more than necessary.
 
I should point out that, although this method has served me well for a
number of years now, it is inherently fragile because it relies on
undocumented internals of both Autoconf and Automake.  There is a very
real possibility that if you also track the latest releases of
GNU Autotools, it may stop working.  Future releases of GNU Autotools will
address the interface problems that force us to use code like this, for
the lack of a better way to do things.
 
 |