GINT

NAME

GINT — Guile Integration Framework

DESCRIPTION

Integrating Guile into a project consists of a set of routine steps,
which, however trivial, require additional efforts from authors and
impose on them an extra maintenance burden. These steps include, among
others, checking for the presence of Guile, determining its version number,
and creating additional Makefile rules. Authors maintaining several projects
that use Guile as an extension language, soon find out that these
steps differ only insigificantly between the projects. It is therefore
natural to move their common denominator into a separate module and share
this module between the projects.

GINT is an attempt to create such a module. It reduces the task of
integrating Guile to importing a submodule and editing a couple of files.

GINT is designed as a Git submodule easily embeddable into any project.
The only requirement for this host project is that it must use GNU Automake
and Autoconf. It is also recommended, but not required, that the host project
use Git for its repository.

INSTALLATION

To illustrate how to use GINT, let's suppose your project has the
following structure:

The purpose of GINT is to provide the autotools magic necessary to
check, at configure time, whether Guile is installed, determine its version
number and location of its components on the local file system, then to
compile and snarf the C sources, and finally, to produce the
documentation files (guile-procedures.texi and guile-procedures.txt).

Installation of GINT consists of the following four steps:

Importing gint submodule.

Editing the top-level Makefile.am

Editing configure.ac

Editing source Makefile.am.

These steps are described in detail in the following subsections.

Import GINT as a submodule

The submodule add command takes two arguments: the submodule repository,
which should be exactly as shown above, and the pathname of the
cloned submodule in your project. This latter is entirely at your option.
Throughout this document we will suppose that the module pathname is
gint. You will need to adjust the examples if you chose another
name for it.

Edit the toplevel Makefile.am

Add -I gint to the ACLOCAL_AMFLAGS variable, and gint to
the SUBDIRS variable. For example:

ACLOCAL_AMFLAGS = -I m4 -I gint
SUBDIRS = gint src

Notice that in SUBDIRS, the gint entry must precede the names of
those directories that depend on it.

Edit the configure.ac file

Obviously, you need to add the submodule's Makefile to the list of
AC_CONFIG_FILES, e.g.:

AC_CONFIG_FILES(Makefile
gint/Makefile
src/Makefile)

Next, add a call to GINT_INIT at an appropriate point.
This macro serves two purposes. First, it informs the gint submodule
about its location relative to the top project directory and configures
its features. Second, it checks for the presence of Guile's binaries
and libraries, verifies if its version is modern enough, and runs a
series of user-supplied commands, depending on the result of this check.

Edit source Makefile.am

The source Makefile.am (or Makefile.am's, if there are several of these, in
separate directories) must include the file gint/gint.mk, which provides
Makefile rules necessary to properly build various files (e.g. .x and
.doc files from corresponding .c sources, etc) and to compute dependencies
between them. Usually, it is OK to use a relative location. For example, in our
sample project the gint and src directories have same parent directory,
therefore we could add to src/Makefile.am the following line:

include ../gint/gint.mk

The rules in gint.mk make certain assumptions about some Makefile
variables. Namely, the following variables must be defined before
including the file: INCLUDES, EXTRA_DIST, CLEANFILES,
DISTCLEANFILES (or MAINTAINERCLEANFILES, if doc-distrib
option is used), SUFFIXES, BUILT_SOURCES. See the
Automake documentation,
for more info on these. If no special value is needed, define each
of them to an empty string (see example below).

Firthermore, the MAKEINFO variable must contain the pathname (not
necessarily an absolute one), of the makeinfo binary. It is initialized
by Automake if your project contains a Makefile.am with the info_TEXINFOS
variable set. If not, you will have to initialize it manually.

Finally, the following GINT-specific variables must be defined:

sitedir

The location where to install site-specific Guile modules. We advise
to set it to:

The GINT_INIT macro

GINT_INIT(DIR, OPTIONS, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)

This macro configures GINT submodule, located in subdirectory
DIR according to the settings given in OPTIONS. It then
verifies if Guile is installed on the system and if so executes
commands supplied by ACTION-IF-FOUND. Additionaly, it sets
a number of substitution variables describing
various details of Guile installation.

Otherwise, if Guile is not installed or is found to be unusable,
ACTION-IF-NOT-FOUND is executed.

Commands to execute if Guile is not found or its version is too old.
If not given, the default action is to print a diagnostic message on
the standard error and abort execution.

The OPTIONS parameter offers a way to control the
functionality provided by GINT_INIT. Its value is a
whitespace-separated list of words. Each word must be either the
name of an option, or the minimum (i.e. the oldest) allowed version
of Guile. For example, to check for Guile 1.8 or later one could
write:

Add generated docfiles to distribution tarball. The following files are
added: *.doc, *.x, guile-procedures.texi and guile-procedures.txt.
Normally they are not distributed and are recreated on each built. A minor
drawback of this approach is that it requires installers to have makeinfo
installed. If this option is given, the files will be included in the
tarball and no rebuild will be necessary.

If this option is used, MAINTAINERCLEANFILES must be defined before
including gint.mk.

Enable generation of .inc files. Each such file contains a set of
export statements, one for each SCM_DEFINE in the corresponding
.c source file. Normally this option is not needed, because it is
more appropriate to define public interfaces using SCM_DEFINE_PUBLIC
macro.

std-site-dir

Set site directory to the standard Guile site directory, as
returned by the %site-dir primitive.

This is one of the locations where Guile looks for its modules.
However, this setting breaks standard distcheck rules and automated builds,
because this directory is normally outside of the installation prefix.
Therefore by default, GINT does not use it. See below, for a description of the method used to determine site directory.

snarf-doc-filter

Use snarf-doc-filter to extract docstrings from C files. GINT offers
two programs for extraction of Scheme docstrings from C sources. By default,
the C implementation is used, mainly because it is much faster than its
Scheme counterpart. By supplying the snarf-doc-filter option, you instruct
GINT to use Scheme implementation instead. See the section
Doc snarfing for a detailed discussion.

By default, the generated configure script always checks for Guile. The
following options modify this behavior:

with-guile

Add a —with-guile option to configure. Do not check for Guile if
configure was called with —with-guile=no (or —without-guile).

without-guile

Same as above, except that Guile checks are disabled by default. I.e. the
configure script checks for Guile only if invoked with the —with-guile
option.

enable-guile

Add a —enable-guile option to configure. Do not check for Guile if
configure was called with —enable-guile=no (or —disable-guile).

disable-guile

Same as above, except that Guile checks are disabled by default. I.e. the
configure script checks for Guile only if invoked with the —enable-guile
option.

Only one of these four options may be given to a GINT_INIT invocation.

If the check for Guile was disabled at configure time, either by default or
by the user's request, the action of GINT_INIT depends on whether it had
been given the ACTION-IF-NOT-FOUND argument. If not, GINT_INIT does
nothing. Otherwise, the ACTION-IF-NOT-FOUND argument is executed just as
if Guile has not been found. If you need to discern between various failure
reasons (check disabled vs. Guile not found or vs. Guile version too
low), use the gint_guile_status variable.

This fragment initializes the GINT module located in modules/gint and
checks for Guile version 1.8 or newer. The resulting script understands
the —with-guile option and sets sitedir to the standard Guile
site directory. The shell variable use_guile is set to yes or no,
depending on whether Guile was found or not.

Notice, that you may not use this macro within a shell conditional, or
within any Autoconf macro that generates such a conditional. In particular,
the following invocation is wrong:

Substitution Variables

Upon successful return, GINT_INIT sets the following Automake
substitution variables:

GUILE_VERSION

The version of Guile, as a string, e.g. 1.9.9. Additionally,
a C preprocessor macro with the same name is defined.

GUILE_VERSION_NUMBER

The version of Guile packed into a decimal number using the following formula:

MAJOR * 1000 + MINOR * 100 + PATCHLEVEL

where MAJOR, MINOR and PATCHLEVEL are the three parts of a version
number, separated by dots. For example, the version string 1.9.9 will produce
the value 1909, and the version 2.0 will yield 2000.

A C preprocessor macro with the same name is also defined.

GUILE_INCLUDES

C compiler flags needed to compile with Guile, as
returned by guile-config compile.

GUILE_LIBS

Loader flags and additional libraries needed to link with libguile, as
returned by guile-config link.

GUILE_SNARF

The full pathname of the guile-snarf binary.

GUILE_TOOLS

The full pathname of the guile-tools binary.

GUILE_SITE

The full pathname of the Guile site-wide module directory.

Shell Variables

The GINT_INIT macro sets the following shell variables:

gint_enable_guile

By default, set to yes. If an option generating
option was used, this variable is set to no if the Guile checks were
disabled (either by default or by the user request) and to yes otherwise.

gint_guile_status

This variable contains the status of the last check. It is ok, if the
check has passed, badversion if the Guile version is older than the
requested minimum and cantlink if Guile was found but the attempt to
link a test program had failed. You may use this variable in the
ACTION-IF-NOT-FOUND argument to GINT_INIT to discern between
various reasons for failure.

gint_guile_debug

Set if guile supports the debugging macros (i.e. SCM_DEVAL_P,
SCM_BACKTRACE_P, SCM_RECORD_POSITIONS_P and SCM_RESET_DEBUG_MODE).

Config.h Defines

GUILE_DEBUG_MACROS

Defined if guile supports the debugging macros (i.e. SCM_DEVAL_P,
SCM_BACKTRACE_P, SCM_RECORD_POSITIONS_P and SCM_RESET_DEBUG_MODE).
See also the gint_guile_debug variable.

Doc Snarfing

Guile interfaces are defined in C files using SCM_DEFINE or
SCM_DEFINE_PUBLIC macros. Among other parameters, these macros also
allow to specify a docstring for the interface being defined.

Doc snarfing is a process of extraction these docstrings from C
sources and combining them into two text files: guile-procedures.texi,
a Texinfo document suitable for inclusion in the project's documentation,
and guile-procedures.txt, which is installed along with the rest of
files and is used by Guile's help function.

Apart from this primary goal, doc snarfing also serves to catch some minor
programming errors, such as using incorrect SCM_ARGn macro in SCM_ASSERT,
etc.

Doc snarfing consists of two phases. C preprocessor is used
on the source file and its output is piped to a special program, called
snarf filter. The purpose of the snarf filter is to extract Guile-related
information from the preprocessed source. This information is stored in
a file with the .doc suffix. The .doc files created in this phase
are then used to produce final files: guile-procedures.texi and
guile-procedures.txt.

The guile-procedures.texi file is created by concatenating all
.doc files together and applying the guile-tools
snarf-check-and-output-texi command to the resulting document. This
command is a part of Guile installation.

The guile-procedures.txt is created by invoking makeinfo with the
guile-procedures.texi file as input.

Unfortunately, Guile installation does not include any snarf filter
program. GINT fixes this oversight and offers two filter implementations:

clexer

This is a default implementation. It is written in C and is
extremely efficient. During bootstrap it requires flex to
convert the clexer.l file into a C source which is then distributed
with the package. Of course, flex is needed only during the bootstrap,
it is not required to compile from a packaged source.

snarf-doc-filter

A filter written entirely in Scheme. It does not require compilation,
but is significantly slower than clexer and therefore is not used
by default. If you wish to use it, add the snarf-doc-filter option to
the invocation of GINT_INIT. It may be feasible only if you require
Guile 1.9.8 or later.

The clexer.l source is written so as to not require any special attention
from your part. The only two points that are worth mentioning are:

It includes <config.h> if the preprocessor symbol HAVE_CONFIG_H
is defined.

It uses strerror function to convert C error numbers to text.

You may wish to supply additional command line options for compiling it,
if your config.h is placed in an unusual location or includes another
file, not accessible within the normal include path and/or if you wish
to supply a replacement for strerror on systems that lack it (which
is extremely rare nowadays). To do so, define variables GINT_INCLUDES
and/or GINT_LDADD in the ACTION-IF-FOUND argument to GINT_INIT:

GINT_INCLUDES

Specifies additional command line options to be appended to the
INCLUDES statement in gint/Makefile.am.

GINT_LDADD

Specifies additional command line options to be appended to the
LDADD statement in gint/Makefile.am.

Notice also that if your code does not require doc snarfing, you
may disable it by supplying the nodoc option to the invocation
of GINT_INIT.

By default, doc files are not included in the distribution tarball, which
means that they will be recreated at build time. Creation of
guile-procedures.txt requires makeinfo, which may not always be present.
To simplify built requirements, you can instruct GINT to include the generated
files to the distribution. To do so, add the doc-distrib option to the
invocation of GINT_INIT. The following files will be included in the
distribution: *.doc, *.x, guile-procedures.texi and
guile-procedures.txt.

THE `SITE DIRECTORY' PROBLEM

Projects installing some Scheme sources would normally want to install
them under Guile's site directory (%site-dir Guile primitive). This way,
Guile will be able to find them without any additional configuration. However,
such usage breaks the standard GNU practice of not installing files outside
of project's install prefix, unless the user explicitly requires so.
As a consequence, it also breaks the standard make distcheck rule.

To avoid this, configuration code generated by GINT macros determines
the location of the site directory using the following algorithm:

Determine actual value of the default Guile site directory, by inspecting
the value returned by the %site-dir primitive.

If that value lies under the current installation prefix, it is accepted
as the installation directory.

Otherwise, if the —with-guile-site-dir option is supplied:

If it is used without arguments, %site-dir is enforced as the
installation directory.

Otherwise, the value of this option is taken as new site
directory. Notice, that this value must be an absolute directory name.

Otherwise, a warning is issued and $(datadir)/guile/site is used as
the site directory.

The use if this algorithm is suppressed and Guile site directory is
used instead, if the GINT_INIT macro was invoked
with the std-site-dir option.