<!--  vim: set sw=2 sts=2 et ft=docbk:

  Part of the A-A-P recipe executive: using autoconf

  Copyright (C) 2002-2003 Stichting NLnet Labs
  Permission to copy and use this file is specified in the file COPYING.
  If this file is missing you can find it here: http://www.a-a-p.org/COPYING

-->

<para>
The autoconf system is often used to configure C programs to be able to
compile them on any Unix system.  This section explains how to use autoconf
with &Aap; in a nice way.  An alternative is to use the
<link linkend="cmd-conf">:conf</link> command of &Aap;. It is much easier to
use and also works on non-Unix systems.  See <xref linkend="user-configure"/>.
</para>


<bridgehead>Running The Configure Script</bridgehead>

<para>
A recipe that uses the configure script that autoconf generates can start like
this:
</para>

<programlisting>
        $BDIR/config.h $BDIR/config.aap :
                                configure config.arg config.h.in config.aap.in
            :sys ./configure `file2string("config.arg")`
            :move {force} config.h config.aap config.log
                                              config.cache config.status $BDIR
        config.arg:
            :touch {exist} config.arg

        :update $BDIR/config.aap
        :include $BDIR/config.aap
</programlisting>

<para>
What happens here is that the "config.aap" target is updated before any of the
building is done.  This is required, because running the configure script
will generate or update the "config.aap" file that influences how the building
is done.
</para>


<bridgehead>Remembering Configure Arguments</bridgehead>

<para>
The arguments for configure are stored in the "config.arg" file.  This
makes it easy to run configure again with the same arguments.  The file is
read with the <link linkend="python-file2string">file2string()</link>
function.  There should be a "config.txt" file that explains all the possible
configure arguments, with examples that can be copied into "config.arg".
Example:
</para>

<programlisting>
        # Select the library to be used for terminal access.  When omitted a
        # series of libraries will be tried.  Useful values:
            --with-tlib=curses
            --with-tlib=termcap
            --with-tlib=termlib
</programlisting>

<para>
The user can now copy one of the example lines to his "config.arg" file.
Example:
</para>

<programlisting>
        # select specific terminal library
            --with-tlib=termcap
</programlisting>

<para>
Comment lines can be used, they must start with a "#".  Note: a comment after
an argument doesn't work, it will be seen as an argument.
</para>

<para>
When updating to a new version of the program, the same "config.arg" file
can still be used.  A "diff" between the old and the new "config.txt" will
show what configure arguments have changed.
</para>


<bridgehead>Variants And Configure</bridgehead>

<para>
"config.aap" and "config.h" are put in $BDIR, because they depend on the
current system.  They might also depend on the variant to be built.  In that
case the
<link linkend="cmd-variant">:variant</link> statement must be before the use
of $BDIR.  However, if the variant is selected by running configure, the
variant must come later.
"config.aap" and "config.h" are then updated when selecting another variant.
</para>

<para>
  For the program to find "config.h" in $BDIR you must add an option to the C
  compiler.  And you have to notify the compiler that the file exists, so that
  it will be included:
</para>

<programlisting>
        INCLUDE += -I$BDIR
        DEFINE += -DHAVE_CONFIG_H
</programlisting>

<para>
The "config.cache", "config.log" and "config.status" files are also moved to
$BDIR.  This means they are not available when running "./configure" again.,
This may be a bit slower, since the cache isn't used, but it is much more
reliable.  And you can view the log of each variant that was build.
</para>


<bridgehead>Running Autoconf</bridgehead>

<para>
For a developer there also needs to be a method to generate the configure
script from configure.in.  This needs to be done even before configure is run.
Prepending this to the example above should work:
</para>

<programlisting>
        configure {signfile = mysign} : configure.in
            :sys autoconf
</programlisting>

<para>
  Normally the "configure" script is distributed with the program, so that a
  user does not need to install and run autoconf.
  The "{signfile = mysign}" attribute on the target is used to avoid running
  autoconf when the user builds the program and the "configure" and
  "configure.in" files are still as they were distributed.  The signatures in
  the "mysign" file, which you must include in the distribution, will match
  and &Aap; knows that "configure" is up-to-date.
  If using the "mysign" file was omitted,
  there would be no signature for the "configure" target and &Aap; would
  decide to run autoconf.
When you change "configure.in" its signature will be different from what is
stored in "mysign" and autoconf will be run.
</para>


<bridgehead>Using A Distributed Configure Script</bridgehead>

<para>
  If you are porting an application that already has a configure script you
  can filter it to make it work with &Aap;.  This means you can use the
  unmodified configure.in.
</para>

<programlisting>
        configure_aap : configure
	:cat configure
		| :eval re.sub("Makefile", "config.aap", stdin)
		>! configure_aap
	:chmod 755 configure_aap
</programlisting>

<para>
  Now you need to execute "configure_aap" instead of "configure" in the first
  example above.
</para>


<bridgehead>Skipping Configuration</bridgehead>

<para>
  Running configure can take quite a bit of time.  And when you are not going
  to build anything that can be annoying.  For example, "aap comment" doesn't
  require configure to run.
</para>

<para>
  Also, configure doesn't work on a non-Unix system.  When you have taken care
  in your code to handle this you can simply skip configure.  This line above
  all the configure code should take care of this:
</para>

<programlisting>
        @if osname() == "posix" and has_build_target():
</programlisting>

<para>
  The <link linkend="python-has-build-target">has_build_target()</link>
  function checks for a target that will do some kind of building, which means
  configure must be run.
</para>


<bridgehead>A Complete Example</bridgehead>

<para>
  Using all the parts mentioned above together we have a fairly complete
  method to handle running autoconf and configure.  This code is used in the
  recipe that builds the Exuberant Ctags program.
</para>

<programlisting>
    #
    # On Unix we run configure to generate config.h and config.aap.
    # This is skipped if there is no building to be done (e.g., for "clean").
    #
    @if osname() == "posix" and has_build_target():

        # "config.h" and "config.aap" are generated in $BDIR, because the are
        # different for each system.
        # Tell the compiler to find config.h in $BDIR.
        INCLUDE += -I$BDIR
        DEFINE += -DHAVE_CONFIG_H

        # Run autoconf when needed, but avoid doing this always, not everybody has
        # autoconf installed.  Include "mysign" in the distribution, it stores the
        # signature of the distributed configure script.
        configure {signfile = mysign} : configure.in
            @if not program_path("autoconf"):
                :print Can't find autoconf, using existing configure script.
            @else:
                :sys autoconf

        # Filter the configure script created by autoconf to generate config.aap
        # instead of Makefile.  This means we can use the unmodified configure.in
        # distributed with ctags.
        configure_aap : configure
            :cat configure
                    | :eval re.sub("Makefile", "config.aap", stdin)
                    >! configure_aap
            :chmod 755 configure_aap

        # Dependency to create config.aap by running the configure script.
        # The "config.arg" file is used for configure arguments.
        :attr config {virtual} {comment = Do configuration only}

        config $BDIR/config.h $BDIR/config.aap :
                    configure_aap config.arg config.h.in config.aap.in
            :sys ./configure_aap `file2string("config.arg")`
            # Move the results into $BDIR.  This also means the cache isn't used
            # the next time, it is unreliable.
            :move {force} config.h config.aap config.log config.cache
                                                               config.status $BDIR

        # Create an empty config.arg when it's missing.
        config.arg:
            :touch {exist} config.arg

        # Update config.aap before including it.  Forcefully when the "reconfig"
        # target is used.
        @if "reconfig" in var2list(_no.TARGETARG):
            :del {force} config.cache config.status
            :update {force} $BDIR/config.aap
        @else:
            :update $BDIR/config.aap

        :include $BDIR/config.aap
</programlisting>
