@c =================================================================== @c
@c    serrano/prgm/project/bigloo/manuals/library.texi                 @c
@c    ------------------------------------------------------------     @c
@c    Author      :  Manuel Serrano                                    @c
@c    Creation    :  Mon Jun 15 15:00:35 1998                          @c
@c    Last change :  Tue Nov 13 06:13:38 2001 (serrano)                @c
@c    ------------------------------------------------------------     @c
@c    Bigloo libraries                                                 @c
@c =================================================================== @c

@c ------------------------------------------------------------------- @c
@c    Libraries                                                        @c
@c ------------------------------------------------------------------- @c
@node Bigloo Libraries, Extending the Runtime System, SRFIs, Top
@comment  node-name,  next,  previous,  up
@chapter Bigloo Libraries
@cindex libraries

Bigloo libraries are collections of global bindings (global variables and
global functions). Bigloo libraries are build on the top of the host
operating system (e.g. Unix) libraries. Because Bigloo uses modules, a
library is not only a bundle of compiled codes and memory locations. A
Bigloo library is splited into several files:

@itemize @bullet
@item one @emph{heap} that describes the locations of the library.
@item several host library files.
@item possibly, C header files.
@item possibly, a compiler initialization file.
@end itemize

Let's consider, for example, a library that implements the @code{format}
Common Lisp facility. Let's suppose we name this library
@code{bformat}. Using a Unix machine, the Bigloo library will consist of
the following files:

@itemize @bullet
@item @code{bformat.heap}: the heap file.
@item @code{libbformat.a}, @code{libbformat.so}, @code{libbformat_u.a}, @code{libbformat_u.so}:
the Unix library files. The file names with a @code{_u} are libraries compiled in
@emph{unsafe} and @emph{optimized} mode.
@item @code{bformat.h}: an include file.
@end itemize

@c ------------------------------------------------------------------- @c
@c    Compiling and linking with a library                             @c
@c ------------------------------------------------------------------- @c
@section Compiling and linking with a library
@cindex compiling and linking with a library
From the user stand point, using a library can be made two ways:

@itemize @bullet
@item Using the Bigloo @code{-library @var{lib-name}} option where 
@var{lib-name} is the name of the Bigloo library (not the name of one 
of the Unix files implementing the library). The name of the library
must be @emph{lower case}. For instance:

@display
$ bigloo foo.scm -library bformat
@end display

@item Using the module clause @code{library}. This second solution prevent from
using a special compilation option. For instance, this module will
automatically compile and link with the @code{bformat} library:

@smalllisp
(module foo
   (library bformat))

...
(format ...)
@end smalllisp
@end itemize

When a Bigloo library @code{lib} is used, Bigloo automatically searches
if a file called @code{lib.init} exists. If such a file exits, it is
loaded at compile-time. That file may specifies compilation flags.

When a Bigloo library @code{lib} is used, the Bigloo linker
automatically searches for a library to be linked against the
application. The name of the file containing the library depends on
the operating system and the back-end used. For instance, under Unix,
for a library called @emph{NAME}, the Bigloo linker searches for a
file called @code{lib@emph{NAME}.a} or @code{lib@emph{NAME}.so} in the
compilation linker path when using the native back-end. It searches
for a file @code{@emph{NAME}.zip} when the JVM back-end is used.

@c ------------------------------------------------------------------- @c
@c    Library and srfi                                                 @c
@c ------------------------------------------------------------------- @c
@section Library and SRFI
@cindex Library and SRFI
@cindex srfi-0: library

Libraries are related to Scheme SRFIs. That is, when a library is used
the SRFI implemented by the library is registered. Registered SRFIs
may be tested by the @code{cond-expand} form (@pxref{SRFIs}).

@c ------------------------------------------------------------------- @c
@c    Library and inline functions                                     @c
@c ------------------------------------------------------------------- @c
@section Library and inline functions
@cindex Library and inline functions

It is illegal for libraries to include inline functions that make use of
new foreign types. By new foreign type, we mean foreign types that are
defined inside the library. A library may contains inline functions but
that inline functions must not even call function using foreign types in
their prototypes. Including inline functions making use of foreign C
type will make the compiler to fail when compiling user code. The
compiler will fail prompting type errors. A library may contains non-inline
functions that make use of new foreign types.

@c ------------------------------------------------------------------- @c
@c    library and repl                                                 @c
@c ------------------------------------------------------------------- @c
@section library and repl
@cindex library and repl

It is possible to implement a "read-eval-print-loop" that is extended
with the facilities implemented inside a library. Because of the Bigloo
module initialization process a module that implements an extended "repl"
must reference a least one of the binding of the library. For instance,
here is a module that implements a "repl" with the @code{format} 
facility available:

@smalllisp
(module format-repl
   (library format))

;; a dummy reference to a facility of the format library
(let ((dummy format))
   (repl)
@end smalllisp


@c ------------------------------------------------------------------- @c
@c    Build a library                                                  @c
@c ------------------------------------------------------------------- @c
@section Building a library
@cindex Building a library

Bigloo libraries require several steps before being completed. 

@itemize @bullet
@item The first step is to build a @emph{library heap}. This is achieved
 using a special compilation mode: @code{-mkaddheap -mkaddlib -addheap}. 
 That is, for your library you have to create a heap associated source file 
 that imports all the binding you want in your library. The heap source file
 must be @emph{excluded} from the source files that will be used to build
 the host library.

Suppose we have a unique source file for the @code{bformat} library. The module
clause of this source file is:

@smalllisp
(module __format
   (export (format . args)
           format:version
           ...
   (eval   (export format)
           (export format:version)
           ...
@end smalllisp

Prior to compiling the library, we have to create the heap associated file
(let's name it @code{make-lib.scm}). This file could be:

@smalllisp
(module __make-lib
   (import (__format "format.scm")))
@end smalllisp

Building it is simple:

@display
bigloo -unsafe -q -mkaddheap -mkaddlib \
     make-lib.scm -addheap format.heap
@end display

The option @code{-mkaddheap} and @code{-mkaddlib} tell Bigloo that it 
is compiling an heap associated file. The option @code{-addheap} tells 
Bigloo the name of the heap file to be produced.

@item The second step is to compile all the library source file. These
compilation must be done using the @code{-mkaddlib} compilation mode. 
For example:

@display
bigloo -O3 -unsafe -mkaddlib              \
   -cc gcc -fsharing -q -rm               \
   -unsafev bformat.scm -o bformat_u.o -c
bigloo -O3 -mkaddlib -g -cg -cc gcc       \
   -fsharing -q -rm                       \
   -unsafev bformat.scm -o bformat.o -c
@end display

The first compilation produces the @emph{unsafe} version the second the 
produced the @emph{debugging} version.

@item The third step is to build the host operating system libraries. There
is no portable way to do this. This operation may looks like:

@display
ar qcv libformat.a format.o
ranlib libformat.a
ld -G -o libformat.so format.o -lm -lc
ar qcv libformat_u.a format_u.o
ranlib libformat_u.a
ld -G -o libformat_u.so format_u.o -lm -lc
@end display
@end itemize

At this time, you are ready to use your library. The Bigloo distribution
contains library exemplar. Considering these examples as a departure point
for new libraries is probably a good idea.

@c ------------------------------------------------------------------- @c
@c    A complete library example                                       @c
@c ------------------------------------------------------------------- @c
@section A complete library example
@cindex A complete library example

For the means of an example let's suppose we want to design a Bigloo
library for 2d points. That library is made of three implementation
files: two C files, @code{point.h} and @code{point.c} and one Scheme
file @code{scm-point.scm}. Here are defined the three files:

@noindent @code{point.h}:
@smalllisp
struct point_2d @{
   double x, y;
@};
@end smalllisp

@noindent @code{point.c}:
@smalllisp
#include <stdio.h>
#include "point.h"

int print_point_2d( struct point_2d *pt ) @{
   printf( "<point-2d: %g, %g>", pt->x, pt->y );
@}
@end smalllisp

@noindent @code{scm-point.scm}:
@smalllisp
(module point
   (include "point.sch")
   (extern  (include "point.h"))
   (export  (make-point::s-point_2d* ::double ::double)
            (print-point             ::s-point_2d*)
            (point?                  ::obj))
   (eval    (export-all)))

(define (make-point::s-point_2d* x::double y::double)
   (s-point_2d* x y))

(define (print-point p::s-point_2d*)
   (print_point_2d p))

(define (point? obj::obj)
   (s-point_2d*? obj)
   obj)
@end smalllisp

We want our library to be composed of the whole exported Scheme
functions. Thus the file to build the heap library could look like:

@smalllisp
(module __make-point-lib
   (import (point "scm-point.scm")))
@end smalllisp

Let's suppose that the @code{point} library requires the @code{libposix}
library. This means that any file linked with the @code{point} library
needs to be also linked with the @code{posix} library. Furthermore, 
programs making use of the @code{point} library needs to include the
@code{point.sch} file. That Scheme file needs in turn the C file 
@code{point.h} otherwise the produced C files won't compile. The need
for the @code{libposix} library and for the @code{point.h} file may be
specified inside the @code{point.init} file. For our current library,
the @code{point.init} file could look like:

@smalllisp
(set! *ld-options*
      (string-append "-L/usr/lib " *ld-options*))

(set! *bigloo-user-lib*
      (cons "-lposix" *bigloo-user-lib*))

(set! *additional-include-foreign*
      (cons "point.h" *additional-include-foreign*))
      
(define-macro (point x y)
   `(make-point ,x ,y))
@end smalllisp

This file updates some compilation variables (@code{*ld-options*},
@code{*bigloo-user-lib*}, @code{*additional-include-foreign*}) and
defines a macro: @code{point}. Because the @code{point.init} file will
be loaded each time a compilation require the @code{point} library is
spawned, user code are allowed to use the @code{point} macro. Here is an
example file making use of the @code{point} library:

@smalllisp
(module example
   (include "point.sch"))

(let ((p (point 2.9 3.5)))
   (print "point?: " (point? p))
   (print "point?: " (point? 4))
   (print-point p)
   (print (eval `(point? ,p)))
   (eval `(print-point ,p))
   (print "done..."))
@end smalllisp

To conclude that example here is the @code{Makefile} used to compile
the @code{point} library, heap file and one example.

@display
# bigloo flags
BIGLOO          = bigloo
BHEAPFLAGS      = -unsafe -q -mkaddheap -mkaddlib -v2
BCOMMONFLAGGS   = -mkaddlib -fsharing -q $(VERBOSE)        \
                  -copt '$(CCOMMONFLAGS)' -cc $(CC)
BSAFEFLAGS      = $(BCOMMONFLAGGS) -cg -O3 -g -cg -unsafev \
                  -eval '(set! *indent* 4)' -rm
BUNSAFEFLAGS    = $(BCOMMONFLAGS) -O4 -unsafe

# cigloo flags
CIGLOO          = cigloo

# cflags
CC              = gcc
CCOMMONFLAGS    = -I.
CSAFEFLAGS      = $(CCOMMONFLAGS)
CUNSAFEFLAGS    = $(CCOMMONFLAGS) -O2

# library objects
SAFE_OBJECT     = olib/scm-point.o olib/point.o
UNSAFE_OBJECT   = olib_u/scm-point.o olib_u/point.o

all: heap lib example

heap: point.heap

point.heap: point.sch scm-point.scm
        $(BIGLOO) $(BHEAPFLAGS) make-lib.scm -addheap point.heap

lib: lib_u lib.a

lib.a: olib $(SAFE_OBJECT)
        ar qcv libpoint.a $(SAFE_OBJECT) 

lib_u: olib_u $(UNSAFE_OBJECT)
        ar qcv libpoint_u.a $(UNSAFE_OBJECT) 

olib:
        mkdir olib

olib_u:
        mkdir olib_u

olib_u/scm-point.o olib/scm-point.o: scm-point.scm
        $(BIGLOO) $(BSAFEFLAGS) $(<F) -o $*.o -c

olib_u/point.o olib/point.o: point.c
        $(CC) $(CSAFEFLAGS) $(<F) -o $*.o -c

point.sch: point.h point.c
        cigloo $^ > point.sch

example: heap lib
        $(BIGLOO) -v2 -L . -library point \
            -static-bigloo example.scm -o example

clean:
        -/bin/rm -f point.heap
        -/bin/rm -f point.sch scm-point.c
        -/bin/rm -fr olib olib_u
        -/bin/rm -f example example.c example.o
        -/bin/rm -f libpoint.a libpoint_u.a
@end display

@c ------------------------------------------------------------------- @c
@c    Library and modules                                              @c
@c ------------------------------------------------------------------- @c
@section Library and modules
@cindex Library and modules

A Bigloo library may be composed of several Bigloo modules (even if in
our example only one module was used). The modules composing the library
are free to import each other. Nevertheless, someone designing a Bigloo
library should be aware that Bigloo importation creates dependences
between modules. A module @code{mod1} that imports a module @code{mod2}
depends on @code{mod2} because @code{mod1} requires @code{mod2} to be
initialized (i.e. @code{mod1} calls to the initialization function of
@code{mod2}). The result is that using @code{import} clauses inside
modules composing a library may create a lot of dependencies between the
object files that are used to build the associated Unix
library. Dependencies should be avoided because they make the Unix
linkers unable to produce small stand-alone programs. Instead of
@code{import} clauses, @code{use} clauses should be
preferred. @code{Use} clauses do not create dependencies because a
module @code{mod1} that @code{use}s a second module @code{mod2} does not
require @code{mod2} to be initialized. Of course, it may happen
situations where the initialization is mandatory and thus, the
@code{import} must not be replaced with a @code{use} clause. The source
code of the Bigloo library makes use of @code{import} and @code{use}
clauses. The Bigloo standard library should be studied as an example.



