Autoconf Support
****************

When Guile is installed, a pkg-config description file and a set of Autoconf macros is installed.  This chapter documents pkg-config and Autoconf support, as well as the high-level guile-tool Autofrisk.

Autoconf Background
===================

As explained in the GNU Autoconf Manual, any package needs configuration at build-time (see Introduction (The GNU Autoconf Manual)).  If your package uses Guile (or uses a package that in turn uses Guile), you probably need to know what specific Guile features are available and details about them.

The way to do this is to write feature tests and arrange for their execution by the configure script, typically by adding the tests to configure.ac, and running autoconf to create configure. Users of your package then run configure in the normal way.

Macros are a way to make common feature tests easy to express. Autoconf provides a wide range of macros (see Existing Tests (The GNU Autoconf Manual)), and Guile installation provides Guile-specific tests in the areas of: program detection, compilation flags reporting, and Scheme module checks.

Autoconf Macros
===============

GNU Guile provides a pkg-config description file, which contains all the information necessary to compile and link C applications that use Guile.  The pkg-config program is able to read this file and provide this information to application programmers; it can be obtained at http://pkg-config.freedesktop.org/.

The following command lines give respectively the C compilation and link flags needed to build Guile-using programs:

     pkg-config guile-EFFECTIVE-VERSION --cflags
     pkg-config guile-EFFECTIVE-VERSION --libs

To ease use of pkg-config with Autoconf, pkg-config comes with a convenient Autoconf macro.  The following example looks for Guile and sets the GUILE_CFLAGS and GUILE_LIBS variables accordingly, or prints an error and exits if Guile was not found:

     PKG_CHECK_MODULES([GUILE], [guile-EFFECTIVE-VERSION])

Guile comes with additional Autoconf macros providing more information, installed as PREFIX/share/aclocal/guile.m4.  Their names all begin with GUILE_.

     [file autoconf-macros.texi not included]

Using Autoconf Macros
=====================

Using the autoconf macros is straightforward: Add the macro "calls" (actually instantiations) to configure.ac, run aclocal, and finally, run autoconf.  If your system doesn't have guile.m4 installed, place the desired macro definitions (AC_DEFUN forms) in acinclude.m4, and aclocal will do the right thing.

Some of the macros can be used inside normal shell constructs: if foo ; then GUILE_BAZ ; fi, but this is not guaranteed.  It's probably a good idea to instantiate macros at top-level.

We now include two examples, one simple and one complicated.

The first example is for a package that uses libguile, and thus needs to know how to compile and link against it.  So we use GUILE_FLAGS to set the vars GUILE_CFLAGS and GUILE_LDFLAGS, which are automatically substituted in the Makefile.

     In configure.ac:

       GUILE_FLAGS

     In Makefile.in:

       GUILE_CFLAGS  = @GUILE_CFLAGS@
       GUILE_LDFLAGS = @GUILE_LDFLAGS@

       myprog.o: myprog.c
               $(CC) -o $ $(GUILE_CFLAGS) $<
       myprog: myprog.o
               $(CC) -o $ $< $(GUILE_LDFLAGS)

The second example is for a package of Guile Scheme modules that uses an external program and other Guile Scheme modules (some might call this a "pure scheme" package).  So we use the GUILE_SITE_DIR macro, a regular AC_PATH_PROG macro, and the GUILE_MODULE_AVAILABLE macro.

     In configure.ac:

       GUILE_SITE_DIR

       probably_wont_work=""

       # pgtype pgtable
       GUILE_MODULE_AVAILABLE(have_guile_pg, (database postgres))
       test $have_guile_pg = no &&
           probably_wont_work="(my pgtype) (my pgtable) $probably_wont_work"

       # gpgutils
       AC_PATH_PROG(GNUPG,gpg)
       test x"$GNUPG" = x &&
           probably_wont_work="(my gpgutils) $probably_wont_work"

       if test ! "$probably_wont_work" = "" ; then
           p="         ***"
           echo
           echo "$p"
           echo "$p NOTE:"
           echo "$p The following modules probably won't work:"
           echo "$p   $probably_wont_work"
           echo "$p They can be installed anyway, and will work if their"
           echo "$p dependencies are installed later.  Please see README."
           echo "$p"
           echo
       fi

     In Makefile.in:

       instdir = @GUILE_SITE@/my

       install:
             $(INSTALL) my/*.scm $(instdir)

Autofrisk
=========

The guile-tools autofrisk command looks for the file modules.af in the current directory and writes out modules.af.m4 containing autoconf definitions for AUTOFRISK_CHECKS and AUTOFRISK_SUMMARY. See Autoconf Background, and see Using Autoconf Macros, for more info.

The modules.af file consists of a series of configuration forms (Scheme lists), which have one of the following formats:

       (files-glob PATTERN ...)                      ;; required
       (non-critical-external MODULE ...)            ;; optional
       (non-critical-internal MODULE ...)            ;; optional
       (programs (MODULE PROG ...) ...)              ;; optional
       (pww-varname VARNAME)                         ;; optional

PATTERN is a string that may contain "*" and "?" characters to be expanded into filenames.  MODULE is a list of symbols naming a module, such as `(srfi srfi-1)'.  VARNAME is a shell-safe name to use instead of probably_wont_work, the default.  This var is passed to `AC_SUBST'. PROG is a string that names a program, such as "gpg".

Autofrisk expands the files-glob pattern(s) into a list of files, scans each file's module definition form(s), and constructs a module dependency graph wherein modules defined by define-module are considered internal and the remaining, external.  For each external module that has an internal dependency, Autofrisk emits a GUILE_MODULE_REQUIRED check (see Autoconf Macros), which altogether form the body of AUTOFRISK_CHECKS.

GUILE_MODULE_REQUIRED causes the configure script to exit with an error message if the specified module is not available; it enforces a strong dependency.  You can temper dependency strength by using the non-critical-external and non-critical-internal configuration forms in modules.af.  For graph edges that touch such non-critical modules, Autofrisk uses GUILE_MODULE_AVAILABLE, and arranges for AUTOFRISK_SUMMARY to display a warning if they are not found.

The shell code resulting from the expansion of AUTOFRISK_CHECKS and AUTOFRISK_SUMMARY uses the shell variable probably_wont_work to collect the names of unfound non-critical modules.  If this bothers you, use configuration form (pww-name foo) in modules.af.

Although Autofrisk does not detect when a module uses a program (for example, in a system call), it can generate AC_PATH_PROG forms anyway if you use the programs configuration form in modules.af.  These are collected into AUTOCONF_CHECKS.

See Using Autofrisk, for some modules.af examples.

Using Autofrisk
===============

Using Autofrisk (see Autofrisk) involves writing modules.af and adding two macro calls to configure.in.  Here is an example of the latter:

     AUTOFRISK_CHECKS
     AUTOFRISK_SUMMARY

Here is an adaptation of the second "GUILE_*" example (see Using Autoconf Macros) that does basically the same thing.

     (files-glob "my/*.scm")
     (non-critical-external (database postgres))
     (programs ((my gpgutils) "gpg"))        ;; (my gpgutils) uses "gpg"

If the SRFI modules (see SRFI Support) were a separate package, we could use guile-tools frisk to find out its dependencies:

     $ guile-tools frisk srfi/*.scm
     13 files, 18 modules (13 internal, 5 external), 9 edges

     x (ice-9 and-let-star)
     			 regular	(srfi srfi-2)
     x (ice-9 syncase)
     			 regular	(srfi srfi-11)
     x (ice-9 rdelim)
     			 regular	(srfi srfi-10)
     x (ice-9 receive)
     			 regular	(srfi srfi-8)
     			 regular	(srfi srfi-1)
     x (ice-9 session)
     			 regular	(srfi srfi-1)

Then, we could use the following modules.af to help configure it:

     (files-glob "srfi/*.scm")
     (non-critical-external          ;; relatively recent
       (ice-9 rdelim)
       (ice-9 receive)
       (ice-9 and-let-star))
     (pww-varname not_fully_supported)