PR modula2/120189 Bugfix to documentation and fix prototypes in m2rts.h

This patch rewrites the Building a shared library section in the
gm2.texi.  The new content addresses the default dynamic module
scaffold and also provides an example of C++ calling the m2 shared
library.  Bootstrapped using lto on amd64.

gcc/ChangeLog:

	PR modula2/120189
	* doc/gm2.texi (Building a shared library): Rewrite.

libgm2/ChangeLog:

	PR modula2/120189
	* libm2iso/m2rts.h (m2iso_M2RTS_RequestDependant): Correct
	parameters.
	(m2iso_M2RTS_ConstructModules): Ditto.
	(m2iso_M2RTS_DeconstructModules): Ditto.

Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>
This commit is contained in:
Gaius Mulley
2026-04-21 02:56:39 +01:00
parent c39e494969
commit 90fb3a5ec4
2 changed files with 105 additions and 18 deletions

View File

@@ -2304,8 +2304,8 @@ intersect.
This section describes building a tiny shared library implemented in
Modula-2 and built with @file{libtool}. Suppose a project consists of
two definition modules and two implementation modules and a program
module @file{a.def}, @file{a.mod}, @file{b.def}, @file{b.mod} and
three definition modules and three implementation modules
@file{a.def}, @file{a.mod}, @file{b.def}, @file{b.mod} and
@file{c.mod}. The first step is to compile the modules using position
independent code. This can be achieved by the following three
commands:
@@ -2316,28 +2316,111 @@ 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
@end example
The second step is to generate the shared library initialization and
finalization routines. We can do this by asking gm2 to generate a
list of dependent modules and then use this to generate the scaffold.
We also must compile the scaffold.
The second step is to link these objects into a shared library.
@example
gm2 -c -g -fmakelist c.mod
gm2 -c -g -fmakeinit -fshared c.mod
libtool --tag=CC --mode=compile g++ -g -c c_m2.cpp -o c_m2.lo
@end example
export LIBDIR=$(gm2 -print-file-name=)../../../../lib64
The third step is to link all these @file{.lo} files.
@example
libtool --mode=link gcc -g c_m2.lo a.lo b.lo c.lo \
-L$(prefix)/lib64 \
-rpath `pwd` -lgm2 -lstdc++ -lm -o libabc.la
libtool --tag=CC --mode=link gcc -g a.lo b.lo c.lo \
-L$@{LIBDIR@} -rpath `pwd` -lm2pim -lm2iso -lstdc++ \
-lm -o libabc.la
@end example
At this point the shared library @file{libabc.so} will have been
created inside the directory @file{.libs}.
This library can be called from C using the following technique.
The define @code{INIT_ORDER} should not be changed as it defines the
initialization order of the core base modules.
The define @code{USER_LIB} is the name of the library dialect and
maybe changed if required.
@example
#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;
@}
@end example
This source file can be compiled and linked using the following
command:
@example
export INCLUDE=$(gm2 -print-file-name=)/m2/m2iso
g++ -I$@{INCLUDE@} -g test.c -L. -l:.libs/libabc.so -L$@{LIBDIR@} -lm2iso
@end example
and finally run using:
@example
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
@end example
@node Interface for Python, Producing a Python module, Building a shared library, Using
@section How to produce swig interface files

View File

@@ -30,7 +30,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
typedef void (*proc_con) (int, char **, char **);
typedef void (*proc_dep) (void);
extern "C" void m2iso_M2RTS_RequestDependant (const char *modulename, const char *libname, const char *dependancy);
extern "C" void m2iso_M2RTS_RequestDependant (const char *modulename, const char *libname,
const char *dependantmodule,
const char *dependantlibname);
extern "C" void m2iso_M2RTS_RegisterModule (const char *modulename, const char *libname,
proc_con init, proc_con fini, proc_dep dependencies);
extern "C" void m2pim_M2RTS_RegisterModule (const char *modulename, const char *libname,
@@ -40,9 +42,11 @@ extern "C" void M2RTS_RegisterModule (const char *modulename, const char *libnam
extern "C" void m2iso_M2_M2RTS_init (void);
extern "C" void m2iso_M2RTS_ConstructModules (const char *modulename, const char *libname,
const char *overrideliborder,
int argc, char *argv[], char *envp[]);
extern "C" void m2iso_M2RTS_Terminate (void);
extern "C" void m2iso_M2RTS_DeconstructModules (void);
extern "C" void m2iso_M2RTS_DeconstructModules (const char *modulename, const char *libname,
int argc, char *argv[], char *envp[]);
extern "C" void m2iso_M2RTS_HaltC (const char *desc, const char *filename,
const char *functionname, int line) __attribute__ ((noreturn));