aboutsummaryrefslogtreecommitdiff
path: root/README
blob: ba1f635fd0986c17c9550b13ff160a4b35bd7956 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
//////////////////////////////////////////////////////////////
This file is in AsciiDoc format.  Use the following command
to convert it to HTML:

     asciidoc README

See end of file for copyright statement.
//////////////////////////////////////////////////////////////
GINT
====
Sergey Poznyakoff <gray@gnu.org>
3, Dec 18, 2013

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:

.Sample project listing
---------------------------------------------------------------------
-rw-r--r-- 1 gray users   2993 2010-04-05 00:15 Makefile.am      <1>
-rw-r--r-- 1 gray users   3026 2010-04-05 19:21 configure.ac     <2>
drwxr-xr-x 2 gray users    240 2010-04-05 02:27 m4/              <3> 
drwxr-xr-x 5 gray users   1992 2010-04-05 19:20 src/             <4>
-rw-r--r-- 1 gray users   1286 2010-04-05 13:18 src/Makefile.am  <5> 
-rw-r--r-- 1 gray users   1034 2010-04-05 13:18 src/iface.c
---------------------------------------------------------------------

<1>  Top-level +Makefile+ source.
<2>  Configuration script source.
<3>  Directory with macro definitions for *aclocal*.
<4>  Source directory.  It contains actual _C_ and +scm+ sources,
   which define new *Guile* interfaces.
<5>  Source +Makefile.am+.

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:

1. Importing +gint+ submodule.
2. Editing the top-level +Makefile.am+
3. Editing +configure.ac+
4. Editing source +Makefile.am+.

These steps are described in detail in the following subsections.

Import GINT as a submodule
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This needs to be done only once:

----------------------------------------------------
git submodule add git://git.gnu.org.ua/gint.git gint
git submodule init
----------------------------------------------------

[[gint-dir]]
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,+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.

In a simplest case, the following line will be enough:

---------
GINT_INIT
---------

For a detailed discussion, see the <<GINT_INIT, macro description>>.

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: +AM_CPPFLAGS+, +EXTRA_DIST+, +CLEANFILES+,
+DISTCLEANFILES+ (or +MAINTAINERCLEANFILES+, if +doc-distrib+
option is used), +SUFFIXES+, +BUILT_SOURCES+.  See the
http://sources.redhat.com/automake/automake.html[`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:

---------------------------------
sitedir = @GUILE_SITE@/$(PACKAGE)
---------------------------------

See <<guile-site-dir, The `site directory' problem>>, for a detailed
discussion of sitedir.

site_DATA::
	A list of modules to install to +sitedir+.
DOT_X_FILES::
	A list of +.x+ files to be generated.
DOT_DOC_FILES::
	A list of +.doc+ files to be generated.

These two can be easily produced from the list of source +c+ files
using http://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html[+make+ substitution references]:

-----------------------------------------------
lib_LTLIBRARIES = libproj.la
libproj_la_SOURCES = iface.c var.c

AM_CPPFLAGS =-I$(top_builddir) -I$(srcdir)
EXTRA_DIST=
DOT_X_FILES=$(libproj_la_SOURCES:.c=.x)
DOT_DOC_FILES=$(libproj_la_SOURCES:.c=.doc)

sitedir = @GUILE_SITE@/$(PACKAGE)
site_DATA = proj.scm

SUFFIXES=
CLEANFILES=
DISTCLEANFILES=
include ../gint/gint.mk
------------------------------------------------

[[GINT_INIT]]
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 <<gint-subst-vars, 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.

All parameters are optional:

DIR::
+GINT+ <<gint-dir,submodule directory>> (defaults to `gint`).

OPTIONS::
A whitespace-separated list of options.

ACTION-IF-FOUND::
Commands to execute if Guile is present.

IF-NOT-FOUND::
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:

------------------------
GINT_INIT([gint], [1.8])
------------------------

The following is a list of valid options:

nodoc::
Disable generation of +.doc+ files (see <<doc-snarfing, Doc snarfing>>).

doc-distrib::
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+.
+
See also <<doc-snarfing, Doc snarfing>>.

inc::
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 <<sitedir,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.  <<guile-site-dir, 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, Doc snarfing>> for a detailed discussion.

[[option-generators]]
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, +gint_guile_status+>> variable.

Here is a more complex example of +GINT_INIT+ usage:

.+GINT_INIT+ macro
-------------------------------------------------------
GINT_INIT([modules/gint], [1.8 with-guile std-site-dir],
          [use_guile=yes],
	  [use_guile=no])
-------------------------------------------------------

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,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:

.*Wrong usage*
-----------------------------------------
AC_ARG_WITH([guile],
            [GINT_INIT([modules/gint])])
-----------------------------------------

Instead, use one of the <<option-generators, option generating>> options,
described above.

[[gint-subst-vars]]
Substitution Variables
----------------------
Upon successful return, +GINT_INIT+ sets the following Automake
substitution variables:

[[GUILE_VERSION]]
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]]
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.

[[sitedir]]
GUILE_SITE::
The full pathname of the Guile site-wide module directory.

[[gint-shell-vars]]
Shell Variables
---------------
The +GINT_INIT+ macro sets the following shell variables:

gint_enable_guile::
By default, set to `yes`.  If an <<option-generators, 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]]
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]]
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]]
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, +gint_guile_debug+>> variable.

GUILE_VERSION::
Same as the <<GUILE_VERSION, +GUILE_VERSION+>> substitution variable.

GUILE_VERSION_NUMBER::
Same as the <<GUILE_VERSION_NUMBER, +GUILE_VERSION_NUMBER+>> substitution
variable.

[[doc-snarfing]]
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_ARG+_n_ 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:

1. It includes +<config.h>+ if the preprocessor symbol +HAVE_CONFIG_H+
is defined.
2. 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
	+AM_CPPFLAGS+ 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+. 

[[guile-site-dir]]
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:

1. Determine actual value of the default Guile site directory, by inspecting
the value returned  by the +%site-dir+ primitive.
2. If that value lies under the current installation prefix, it is accepted
as the installation directory.
3. Otherwise, if the +--with-guile-site-dir+ option is supplied:
 a. If it is used without arguments, +%site-dir+ is enforced as the
    installation directory.
 b. Otherwise, the value of this option is taken as new site
    directory.  Notice, that this value must be an absolute directory name.
4. 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,+GINT_INIT+>> macro was invoked
with the +std-site-dir+ option.

FILES
-----
The package consists of the following files:
------------------------------------------------------
Makefile.am        <1>
README             <2>
clexer.l           <3> 
extract-exports    <4>
gint.m4            <5>
gint.mk            <6>
guile.m4           <7>
snarf-doc-filter   <8>
------------------------------------------------------

<1>  Makefile for building +GINT+ components.
<2>  The source file for this documentation.
<3>  Source of the +clexer+, a program for extracting docstrings and
     similar information from C files.
<4>  Auxiliary program for converting +.doc+ files into a series of
     Guile +export+ declarations.
<5>  Source of the +GINT_INIT+ macro.
<6>  Makefile to be included from the host project's +Makefile.am+.
<7>  Auxiliary defines for +GINT_INIT+.
<8>  Alternative implementation of +clexer+, written in Scheme.

COPYRIGHT
---------
[verse]
Copyright (C) 2010, 2013 http://gray.gnu.org.ua[Sergey Poznyakoff]
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html[<http://gnu.org/licenses/gpl.html>].
This is free software: you are free  to  change  and  redistribute  it.
There is NO WARRANTY, to the extent permitted by law.

Return to:

Send suggestions and report system problems to the System administrator.