|  9.2.3 Beginnings of a `configure.in' 
Now that I have some code, I can run autoscanto generate a
preliminary`configure.in'.
 autoscanwill examine all of
the sources in the current directory tree looking for common points of
non-portability, adding macros suitable for detecting the discovered
problems.autoscangenerates the following in
`configure.scan': 
 |  | 
 # Process this file with autoconf to produce a configure script.
AC_INIT(sic/eval.h)
# Checks for programs.
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(strings.h unistd.h)
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror)
AC_OUTPUT()
 | 
 
 
Since the generated `configure.scan' does not overwrite your
project's `configure.in', it is a good idea to run
autoscanperiodically even in established project source
trees, and compare the two files.  Sometimesautoscanwill
find some portability issue you have overlooked, or weren't aware of. 
Looking through the documentation for the macros in this
`configure.scan',
 AC_C_CONSTandAC_TYPE_SIZE_Twill
take care of themselves (provided I ensure that `config.h' is
included into every source file), andAC_HEADER_STDCandAC_CHECK_HEADERS(unistd.h)are already taken care of in
`common.h'. 
autoscanis no silver bullet!  Even here in this
simple example, I need to manually add macros to check for the presence
of `errno.h': 
 |  | 
 AC_CHECK_HEADERS(errno.h strings.h unistd.h)
 | 
 
I also need to manually add the Autoconf macro for generating
`config.h'; a macro to initialise automakesupport; and a
macro to check for the presence ofranlib.  These should go
close to the start of `configure.in': 
 |  | 
 ...
AC_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(sic, 0.5)
AC_PROG_CC
AC_PROG_RANLIB
...
 | 
 
Recall that the use of bzeroin 9.2.1.2 Memory Management is not
entirely portable.  The trick is to provide abzerowork-alike,
depending on which functions Autoconf detects, by adding the following
towards the end of `configure.in': 
 |  | 
 ...
AC_CHECK_FUNCS(bzero memset, break)
...
 | 
 
With the addition of this small snippet of code to `common.h', I
can now make use of bzeroeven when linking with a C library
that has no implementation of its own: 
 |  | 
 #if !HAVE_BZERO && HAVE_MEMSET
# define bzero(buf, bytes)      ((void) memset (buf, 0, bytes))
#endif
 | 
 
An interesting macro suggested by autoscanisAC_CHECK_FUNCS(strerror).  This tells me that I need to provide a
replacement implementation ofstrerrorfor the benefit of
architectures which don't have it in their system libraries.  This is
resolved by providing a file with a fallback implementation for the
named function, and creating a library from it and any others that
`configure' discovers to be lacking from the system library on the
target host. 
You will recall that `configure' is the shell script the end user
of this package will run on their machine to test that it has all the
features the package wants to use.  The library that is created will
allow the rest of the project to be written in the knowledge that any
functions required by the project but missing from the installers system
libraries will be available nonetheless.  GNU `libiberty'
comes to the rescue again -- it already has an implementation of
`strerror.c' that I was able to use with a little modification.
 
Being able to supply a simple implementation of strerror, as the
`strerror.c' file from `libiberty' does, relies on there being
a well definedsys_errlistvariable.  It is a fair bet that if
the target host has nostrerrorimplementation, however, that the
systemsys_errlistwill be broken or missing.  I need to write a
configure macro to check whether the system definessys_errlist,
and tailor the code in `strerror.c' to use this knowledge. 
To avoid clutter in the top-level directory, I am a great believer in
keeping as many of the configuration files as possible in their own
sub-directory.   First of all, I will create a new directory called
`config' inside the top-level directory, and put
`sys_errlist.m4' inside it:
 
 |  | 
 AC_DEFUN([SIC_VAR_SYS_ERRLIST],
[AC_CACHE_CHECK([for sys_errlist],
sic_cv_var_sys_errlist,
[AC_TRY_LINK([int *p;], [extern int sys_errlist; p = &sys_errlist;],
            sic_cv_var_sys_errlist=yes, sic_cv_var_sys_errlist=no)])
if test x"$sic_cv_var_sys_errlist" = xyes; then
  AC_DEFINE(HAVE_SYS_ERRLIST, 1,
    [Define if your system libraries have a sys_errlist variable.])
fi])
 | 
 
I must then add a call to this new macro in the `configure.in' file
 being careful to put it in the right place --
somewhere between typedefs and structures and library
functions according to the comments in `configure.scan':
 
 
GNU Autotools can also be set to store most of their files in a
subdirectory, by calling the AC_CONFIG_AUX_DIRmacro near the top
of `configure.in', preferably right afterAC_INIT: 
 |  | 
 AC_INIT(sic/eval.c)
AC_CONFIG_AUX_DIR(config)
AM_CONFIG_HEADER(config.h)
...
 | 
 
Having made this change, many of the files added by running
autoconfandautomake --add-missingwill be put in
the aux_dir. 
The source tree now looks like this:
 
 |  | 
 sic/
  +-- configure.scan
  +-- config/
  |     +-- sys_errlist.m4
  +-- replace/
  |     +-- strerror.c
  +-- sic/
        +-- builtin.c
        +-- builtin.h
        +-- common.h
        +-- error.c
        +-- error.h
        +-- eval.c
        +-- eval.h
        +-- list.c
        +-- list.h
        +-- sic.c
        +-- sic.h
        +-- syntax.c
        +-- syntax.h
        +-- xmalloc.c
        +-- xstrdup.c
        +-- xstrerror.c
 | 
 
In order to correctly utilise the fallback implementation,
AC_CHECK_FUNCS(strerror)needs to be removed andstrerroradded toAC_REPLACE_FUNCS: 
 |  | 
 # Checks for library functions.
AC_REPLACE_FUNCS(strerror)
 | 
 
This will be clearer if you look at the `Makefile.am' for the
`replace' subdirectory:
 
 |  | 
 ## Makefile.am -- Process this file with automake to produce Makefile.in
INCLUDES                =  -I$(top_builddir) -I$(top_srcdir)
noinst_LIBRARIES        = libreplace.a
libreplace_a_SOURCES        = dummy.c
libreplace_a_LIBADD        = @LIBOBJS@
 | 
 
The code tells automakethat I want to build a library for use
within the build tree (i.e. not installed -- `noinst'), and that
has no source files by default.  The clever part here is that when
someone comes to install Sic, they will runconfigurewhich
will test forstrerror, and add `strerror.o' toLIBOBJSif the target host environment is missing its own
implementation.  Now, when `configure' creates
`replace/Makefile' (as I asked it to withAC_OUTPUT),
`@LIBOBJS@' is replaced by the list of objects required on the
installer's machine. 
Having done all this at configure time, when my user runs
make, the files required to replace functions missing
from their target machine will be added to `libreplace.a'. 
Unfortunately this is not quite enough to start building the project.
First I need to add a top-level `Makefile.am' from which to
ultimately create a top-level `Makefile' that will descend into
the various subdirectories of the project:
 
 |  | 
 ## Makefile.am -- Process this file with automake to produce Makefile.in
SUBDIRS = replace sic
 | 
 
And `configure.in' must be told where it can find instances of
Makefile.in: 
 |  | 
 AC_OUTPUT(Makefile replace/Makefile sic/Makefile)
 | 
 
I have written a bootstrapscript for Sic, for details see
8. Bootstrapping: 
 |  | 
 #! /bin/sh
autoreconf -fvi
 | 
 
The `--foreign' option to automaketells it to relax
the GNU standards for various files that should be present in a
GNU distribution.  Using this option saves me from having to create
empty files as we did in 5. A Minimal GNU Autotools Project. 
Right.  Let's build the library!  First, I'll run bootstrap: 
 |  | 
 $ ./bootstrap
+ aclocal -I config
+ autoheader
+ automake --foreign --add-missing --copy
automake: configure.in: installing config/install-sh
automake: configure.in: installing config/mkinstalldirs
automake: configure.in: installing config/missing
+ autoconf
 | 
 
The project is now in the same state that an end-user would see, having
unpacked a distribution tarball.  What follows is what an end user might
expect to see when building from that tarball:
 
 |  | 
 $ ./configure
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
checking for working autoconf... found
checking for working automake... found
checking for working autoheader... found
checking for working makeinfo... found
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for ranlib... ranlib
checking how to run the C preprocessor... gcc -E
checking for ANSI C header files... yes
checking for unistd.h... yes
checking for errno.h... yes
checking for string.h... yes
checking for working const... yes
checking for size_t... yes
checking for strerror... yes
updating cache ./config.cache
creating ./config.status
creating Makefile
creating replace/Makefile
creating sic/Makefile
creating config.h
 | 
 
Compare this output with the contents of `configure.in', and notice
how each macro is ultimately responsible for one or more consecutive
tests (via the Bourne shell code generated in `configure').  Now
that the `Makefile's have been successfully created, it is safe to
call maketo perform the actual compilation: 
 |  | 
 $ make
make  all-recursive
make[1]: Entering directory `/tmp/sic'
Making all in replace
make[2]: Entering directory `/tmp/sic/replace'
rm -f libreplace.a
ar cru libreplace.a
ranlib libreplace.a
make[2]: Leaving directory `/tmp/sic/replace'
Making all in sic
make[2]: Entering directory `/tmp/sic/sic'
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c builtin.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c error.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c eval.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c list.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c sic.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c syntax.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c xmalloc.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c xstrdup.c
gcc -DHAVE_CONFIG_H -I. -I. -I.. -I..    -g -O2 -c xstrerror.c
rm -f libsic.a
ar cru libsic.a builtin.o error.o eval.o list.o sic.o syntax.o xmalloc.o
xstrdup.o xstrerror.o
ranlib libsic.a
make[2]: Leaving directory `/tmp/sic/sic'
make[1]: Leaving directory `/tmp/sic'
 | 
 
On this machine, as you can see from the output of configureabove, I have no need of the fallback implementation ofstrerror,
so `libreplace.a' is empty.  On another machine this might not be
the case.  In any event, I now have a compiled `libsic.a' -- so
far, so good. 
 |