Building a shared library (The GNU Modula-2 Compiler)

### 2.14 Building a shared library ¶

This section describes building a tiny shared library implemented in Modula-2 and built with `libtool`. Suppose a project consists of three definition modules and three implementation modules `a.def`, `a.mod`, `b.def`, `b.mod` and `c.mod`. The first step is to compile the modules using position independent code. This can be achieved by the following three commands:

    libtool --tag=CC --mode=compile gm2 -g -c a.mod -o a.lo
    libtool --tag=CC --mode=compile gm2 -g -c b.mod -o b.lo
    libtool --tag=CC --mode=compile gm2 -g -c c.mod -o c.lo

The second step is to link these objects into a shared library.

    export LIBDIR=$(gm2 -print-file-name=)../../../../lib64

    libtool --tag=CC --mode=link gcc -g a.lo b.lo c.lo \
      -L${LIBDIR} -rpath `pwd` -lm2pim -lm2iso -lstdc++ \
      -lm -o libabc.la

At this point the shared library `libabc.so` will have been created inside the directory `.libs`.

This library can be called from C using the following technique. The define `INIT_ORDER` should not be changed as it defines the initialization order of the core base modules. The define `USER_LIB` is the name of the library dialect and maybe changed if required.

    #include <stdio.h>
    #include <m2rts.h>

    #define INIT_ORDER "m2iso:RTentity,m2iso:Storage," \
                       "m2iso:SYSTEM,m2iso:M2RTS," \
                       "m2iso:RTExceptions,m2iso:IOLink"

    #define USER_LIB NULL

    /* Add the runtime dependency for this file on modules a, b and c.  */

    void
    dep (void)
    {
      m2iso_M2RTS_RequestDependant (__FILE__, USER_LIB, "c", USER_LIB);
      m2iso_M2RTS_RequestDependant (__FILE__, USER_LIB, "b", USER_LIB);
      m2iso_M2RTS_RequestDependant (__FILE__, USER_LIB, "a", USER_LIB);
    }

    void
    init (int, char *[], char *[])
    {
      printf ("test.c:init\n");
    }

    void
    fini (int, char *[], char *[])
    {
      printf ("test.c:fini\n");
    }

    void
    construct_scaffold (int argc, char *argv[], char *envp[])
    {
      m2iso_M2RTS_RegisterModule (__FILE__, USER_LIB,
                                  init, fini, dep);
      m2iso_M2RTS_ConstructModules (__FILE__, USER_LIB,
                                    INIT_ORDER, argc, argv, envp);
    }

    void
    deconstruct_scaffold (int argc, char *argv[], char *envp[])
    {
      m2iso_M2RTS_DeconstructModules (__FILE__, USER_LIB,
                                      argc, argv, envp);
    }

    int
    main (int argc, char *argv[], char *envp[])
    {
      printf ("main starts\n");
      construct_scaffold (argc, argv, envp);
      printf ("main application goes here\n");
      deconstruct_scaffold (argc, argv, envp);
      printf ("main tidying up\n");
      return 0;
    }

This source file can be compiled and linked using the following command:

    export INCLUDE=$(gm2 -print-file-name=)/m2/m2iso
    g++ -I${INCLUDE} -g test.c -L. -l:.libs/libabc.so -L${LIBDIR} -lm2iso

and finally run using:

    LD_LIBRARY_PATH=.libs:${LIBDIR} ./a.out

    main starts
    init: module a
    init: module b
    init: module c
    test.c:init
    main application goes here
    test.c:fini
    finish: module c
    finish: module b
    finish: module a
    main tidying up