| Ilya Zakharevich on Wed, 16 Oct 2002 23:05:23 -0700 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| [PATCH CVS] dynamic linking on OS/2 |
This patch
a) Adds a new file README.os2 (please update the distribution-build process);
b) Enables the dynamic-linking build on OS/2 (with the limitation
discussed in README.os2);
c) Enables (on EMX) the style of signal handling (SysV style) which the PARI
core expects;
Before: One could interrupt GP only twice: once by ^C, once by ^Break;
The second-time deliveries of these signals did not
achieve anything.
Now: ^Break still works only once (?!). But ^C works reliably.
(The difference between BSD-style and SysV-style is still voodoo
for me, I just tried to compile with no switches, with -Zbsd-signals
and -Zsysv-signals, and choose what work best. ;-)
d) Enables the same optimizations flags for OS/2 as for Linux.
e) Better emulation of dlopen(NULL, flags) on OS/2. The old version
was relying on installing load/unload-DLL callbacks which does
not scale well (would not work if the static PARI library would be
included in some third-party DLL which wants to install such a
callback itself).
f) Fixes a wrong error message from the dlopen() imlementation (in a
branch which probably would never be reached by PARI ;-]).
Enjoy,
Ilya
--- ./config/Makefile.SH-pre1 Tue Oct 15 23:32:52 2002
+++ ./config/Makefile.SH Wed Oct 16 21:36:22 2002
@@ -32,8 +32,15 @@ esac
language=`ls $src_dir/language/*.c | sed 's,.*/\(.*\)\.c,\1,'`
basemath=`ls $src_dir/basemath/*.c | sed 's,.*/\(.*\)\.c,\1,'`
modules=`ls $src_dir/modules/*.c | sed 's,.*/\(.*\)\.c,\1,'`
+lib_prefix=lib
+dllib_prefix=lib
case "$osname" in
- os2) systems=os2;;
+ os2) systems=os2; dllib_prefix="";
+ lib_prefix=lib # Different, to allow gp-dyn link with DLL
+ export_lib_create=emximp; export_lib='$(DLLIBPARI)$(_A)'
+ export_file=pari.def; export_create="emxexp -u"
+ # Actually, the build will fail until the switch to -Zomf...
+ dlld_ignore=- ;;
*) systems=;;
esac
@@ -195,12 +202,15 @@ AS = $AS
ASFLAGS = $ASFLAGS
AR = ar
-CC = $CC
+CC_FLAVOR =
+CC = $CC \$(CC_FLAVOR)
CPPFLAGS = $CPPFLAGS
CFLAGS = $cflags
-LD = $LD
+LD_FLAVOR = \$(CC_FLAVOR)
+LD = $LD \$(LD_FLAVOR)
LDFLAGS = $LDFLAGS
-DLLD = $DLLD
+DLLD_FLAVOR = \$(LD_FLAVOR)
+DLLD = $DLLD \$(DLLD_FLAVOR)
DLLDFLAGS = $DLLDFLAGS
EXTRADLLDFLAGS = $EXTRADLLDFLAGS
CPP = $CPP
@@ -221,12 +231,20 @@ CPP = $CPP
_O = .o
_A = .a
-LIB_PREFIX = lib
-LIBPARI = \$(LIB_PREFIX)$libpari_base
-LIBPARI_STA= \$(LIBPARI)\$(_A)
-LIBPARI_SO = \$(LIBPARI).$DLSUFFIX
+LIB_PREFIX = $lib_prefix
+DLLIB_PREFIX = $dllib_prefix
+LIBPARI_BASE = $libpari_base
+LIBPARI = \$(LIB_PREFIX)\$(LIBPARI_BASE)
+DLLIBPARI = \$(DLLIB_PREFIX)\$(LIBPARI_BASE)
+LIBPARI_STA = \$(LIBPARI)\$(_A)
+LIBPARI_SO = \$(DLLIBPARI).$DLSUFFIX
LIBPARI_DYN = \$(LIBPARI_SO)$sodest
LIBPARI_SONAME= \$(LIBPARI_SO)$soname
+EXPORT_FILE = $export_file
+EXPORT_CREATE = $export_create
+EXPORT_LIB = $export_lib
+EXPORT_LIB_CREATE = $export_lib_create
+DLLD_IGNORE = $dlld_ignore
RUNPTH = $RUNPTH
RUNPTH_FINAL = $RUNPTH_FINAL
@@ -240,6 +258,7 @@ DYNRELOC = $DYNRELOC
RM = rm -f
MV = mv -f
LN = $ln_s
+CP_F = cp -f
# Change these installation directories to suit your needs.
# DESTDIR is used to install to a false hierachy (to build a Debian package)
@@ -504,15 +523,32 @@ if test -z "$DLLD"; then
EOT
else
+ if test -n "$export_file"; then
+ cat >> $file << EOT
+
+EXPORT_FILE_BASE = $src/systems/os2/pari.def.base
+VERSION_VERBOSE = $pari_release_verbose
+
+\$(EXPORT_FILE): \$(OBJS) \$(EXPORT_FILE_BASE)
+ cat \$(EXPORT_FILE_BASE) | sed 's/<DLL_BASE>/\$(DLLIBPARI)/' | sed 's/<VENDOR>/www.parigp-home.de\//' | sed 's/<VERSION>/\$(VERSION_VERBOSE)/' | sed 's/<DESCR>/GP\/PARI compiled with \$(CFLAGS)/' > \$@
+ \$(EXPORT_CREATE) \$(OBJS) >> \$@
+
+\$(DLLIBPARI)\$(_A): \$(EXPORT_FILE)
+ \$(EXPORT_LIB_CREATE) -o \$@ \$(EXPORT_FILE)
+
+EOT
+ fi
if test -z "$DYNLIBS"; then
cat >> $file << EOT
-gp-dyn: \$(OBJSGP) \$(LIBPARI_DYN) \$(GNUPLOT_OBJS)
+
+gp-dyn: \$(OBJSGP) \$(LIBPARI_DYN) \$(GNUPLOT_OBJS) \$(EXPORT_LIB)
\$(RM) \$@
\$(LD) -o \$@ \$(LDFLAGS) \$(OBJSGP) \$(GNUPLOT_OBJS) \$(RUNPTH) \$(TOPLDDYN) \$(LDDYN) \$(PLOTLIBS) \$(LIBS)
-\$(LIBPARI_DYN): \$(OBJS)
+\$(LIBPARI_DYN): \$(OBJS) \$(EXPORT_FILE)
-\$(RM) \$(LIBPARI_DYN)
- \$(DLLD) -o \$@ \$(DLLDFLAGS) \$(OBJS) \$(EXTRADLLDFLAGS)
+ \$(DLLD_IGNORE)\$(DLLD) -o \$@ \$(DLLDFLAGS) \$(OBJS) \$(EXTRADLLDFLAGS) \$(EXPORT_FILE)
+
EOT
if test "$soname" != "$sodest"; then
cat >> $file << EOT
--- ./Configure-pre1 Tue Oct 15 23:46:48 2002
+++ ./Configure Wed Oct 16 22:37:18 2002
@@ -37,14 +37,15 @@ extract_dir_list="$doc_dir $emacs_dir $m
# Version number and patch level.
. $config_dir/version
version=$VersionMajor.$VersionMinor
-pari_release="$VersionMajor.$VersionMinor.$patch"
+pari_release="$version.$patch"
if test `expr $VersionMinor % 2` = 1; then
- echo "Configuring pari-$version.$patch (STABLE)"
+ pari_release_verbose="$pari_release (STABLE)"
libpari_base=pari
else
- echo "Configuring pari-$version.$patch (DEVELOPMENT VERSION)"
+ pari_release_verbose="$pari_release (DEVELOPMENT VERSION)"
libpari_base=pari-$version
fi
+echo "Configuring pari-$pari_release_verbose"
cd $config_dir
@@ -518,11 +519,12 @@ if test -n "$__gnuc__"; then
case "$osname-$arch" in hpux-*) DLCFLAGS=-fPIC;; esac
# Specific optimisations for some architectures
case "$osname-$arch" in
- linux-i?86|cygwin*) OPTFLAGS="$OPTFLAGS \
+ linux-i?86|cygwin*|os2-*) OPTFLAGS="$OPTFLAGS \
-malign-loops=2 -malign-jumps=2 -malign-functions=2";;
- os2-*) cflags=-Zmt;;
*-sparcv8*) cflags=-mv8;;
esac
+ if test "X$osname" = os2; then cflags=-Zmt; fi
+
# omit-frame-pointer incompatible with -pg
PRFFLAGS="-pg $OPTFLAGS"
case "$optimization" in
@@ -639,9 +641,10 @@ case "$osname-$arch" in
full|profiling) LDFLAGS="-g0 -O4 $LDFLAGS";;
esac;;
solaris-*) LD=$CC; LDFLAGS=$cflags; runpathprefix=-R ;;
- os2-*) LD=$CC; LDFLAGS="$cflags -Zexe"
+ os2-*) LD=$CC; cflags="$cflags -Zsysv-signals"; LDFLAGS="$cflags -Zexe"
+ DLLD=$LD; DLLDFLAGS="$cflags -Zdll"
case "$optimization" in
- full) LDFLAGS="$LDFLAGS -s";;
+ full) LDFLAGS="$LDFLAGS -s"; DLLDFLAGS="$DLLDFLAGS -s";;
esac;;
*) LD=$CC; LDFLAGS=$cflags ;;
esac
@@ -685,6 +688,10 @@ if test "$optimization" = profiling; the
# cygwin*) soname= ; sodest= ; DLSUFFIX=dll;;
hpux-*) soname= ; sodest= ; DLSUFFIX=sl;;
irix-*) soname= ; sodest= ;;
+ os2-*) soname= ; sodest= ; DLSUFFIX=dll
+ # DLL names better be 8+3
+ libpari_base=`echo "$libpari_base" | sed 's/\./_/g'`
+ ;;
*) DLLD=;;
esac
fi
@@ -720,6 +727,7 @@ if test -n "$DLLD"; then
esac;;
sunos-*) DLLDFLAGS="-assert nodefinitions" ;;
solaris-*) DLLDFLAGS="-G -h \$(LIBPARI_SONAME)" ;;
+ os2-*) ;;
*) DLLD=;;
esac
fi
@@ -1374,7 +1382,7 @@ case "$osname" in
esac
for variable in\
- pari_release\
+ pari_release pari_release_verbose\
libpari_base version TOP config_dir src_dir emacs_dir doc_dir\
bindir includedir mandir miscdir libdir datadir\
optimization objdir static suffix\
--- ./src/systems/os2/pari.def.base-pre1 Sun Jun 9 11:15:08 2002
+++ ./src/systems/os2/pari.def.base Wed Oct 16 21:25:20 2002
@@ -1,6 +1,7 @@
-LIBRARY 'pari' INITINSTANCE TERMINSTANCE
-; Can't put http://www.parigp-home.de/, since it is split on :
-DESCRIPTION '@#www.parigp-home.de/:@VERSION@#@GP/PARI compiled with @CFLAGS@
+LIBRARY '<DLL_BASE>' INITINSTANCE TERMINSTANCE
+; Can't put http://www.parigp-home.de/ in VENDOR, since it is split on :
+; One needs to be glad that www.parigp-home.de/ is good enough...
+DESCRIPTION '@#<VENDOR>:<VERSION>#@<DESCR>'
CODE LOADONCALL
DATA LOADONCALL NONSHARED MULTIPLE
EXPORTS
--- ./src/systems/os2.c-pre1 Sun Jun 9 11:15:08 2002
+++ ./src/systems/os2.c Wed Oct 16 03:58:12 2002
@@ -33,6 +33,36 @@ unsigned long _DLL_InitTerm(unsigned lon
#endif
+HMODULE
+find_myself(void)
+{
+
+ static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf,
+ ULONG * Offset, ULONG Address);
+ HMODULE doscalls_h, mod;
+ static int failed;
+ ULONG obj, offset, rc;
+ char buf[260];
+
+ if (failed)
+ return 0;
+ failed = 1;
+ doscalls_h = (HMODULE)dlopen("DOSCALLS",0);
+ if (!doscalls_h)
+ return 0;
+/* {&doscalls_handle, NULL, 360}, */ /* DosQueryModFromEIP */
+ rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP);
+ if (rc)
+ return 0;
+ rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen);
+ if (rc)
+ return 0;
+ failed = 0;
+ handle_found = 1;
+ dllHandle = mod;
+ return mod;
+}
+
void *
dlopen(char *path, int mode)
{
@@ -43,22 +73,25 @@ dlopen(char *path, int mode)
fail[0] = 0;
if (!path) { /* Our own handle. */
- if (handle_found) {
+ if (handle_found || find_myself()) {
if (handle_loaded)
return (void*)dllHandle;
rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname);
if (rc) {
strcpy(fail, "can't find my DLL name by the handle");
+ retcode = rc;
return 0;
}
rc = DosLoadModule(fail, sizeof fail, dllname, &handle);
if (rc) {
strcpy(fail, "can't load my own DLL");
+ retcode = rc;
return 0;
}
handle_loaded = 1;
goto ret;
}
+ retcode = ERROR_MOD_NOT_FOUND;
strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM");
return 0;
}
@@ -78,8 +111,10 @@ dlopen(char *path, int mode)
int n = beg+8-path;
memmove(tmp, path, n);
memmove(tmp+n, dot, strlen(dot)+1);
- if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0)
+ rc = DosLoadModule(fail, sizeof fail, tmp, &handle);
+ if (rc == 0)
goto ret;
+ retcode = rc;
}
handle = 0;
@@ -88,6 +123,8 @@ dlopen(char *path, int mode)
return (void *)handle;
}
+#define ERROR_WRONG_PROCTYPE 0xffffffff
+
void *
dlsym(void *handle, char *symbol)
{
@@ -100,7 +137,7 @@ dlsym(void *handle, char *symbol)
rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type);
if (rc == 0 && type == PT_32BIT)
return (void *)addr;
- rc = ERROR_CALL_NOT_IMPLEMENTED;
+ rc = ERROR_WRONG_PROCTYPE;
}
retcode = rc;
return NULL;
@@ -114,8 +151,13 @@ dlerror(void)
if (retcode == 0)
return NULL;
- if (DosGetMessage(NULL, 0, buf, sizeof buf - 1, retcode,
- "OSO001.MSG", &len)) {
+ if (retcode == ERROR_WRONG_PROCTYPE) {
+ strcpy(buf, "Wrong procedure type");
+ len = strlen(buf);
+ }
+ if ((retcode != ERROR_WRONG_PROCTYPE)
+ && DosGetMessage(NULL, 0, buf, sizeof buf - 1, retcode,
+ "OSO001.MSG", &len)) {
if (fail[0])
sprintf(buf,
"OS/2 system error code %d, possible problematic module: '%s'",
--- ./README.os2-pre1 Wed Oct 16 21:54:16 2002
+++ ./README.os2 Wed Oct 16 22:45:24 2002
@@ -0,0 +1,42 @@
+On OS/2 the build goes the same way as on Unix, e.g.,
+
+ sh Configure
+ make gp
+ make bench
+
+With the current implementation of install(), one can load the functions from
+the PARI library only if the GP executable is build for dynamic linking.
+
+By default, the build will go to an AOUT-type executables (to simplify
+the logic of Configure, and enable restricted binary compatibility with
+DOS/Windows). Unfortunately, AOUT-type DLLs are very restricted; thus
+the build of dynamically linked target fails.
+
+To build with OMF-type target
+
+ cd Oos2-ix86
+ make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll" RLLIBS=-lreadline_import DLLD_IGNORE= bench
+
+This build constructs a working DLL. Both -Zomf and -Zcrtdll are crucial to
+have a functioning DLL (see EMX documentation for details).
+Use of the the readline-DLL (via the readline_import.lib library) is not only
+a convenience, but also statically linked readline library are often broken;
+sigh...
+
+To use the gnuplot-engine DLL gnpltdrw.DLL, one can give Configure the option
+--graphic=gnuplot-dynamic,gnpltdrw. Thus the build process looks like this:
+
+ sh Configure --graphic=gnuplot-dynamic,gnpltdrw
+ make gp
+ cd Oos2-ix86
+ make _O=.obj _A=.lib CC_FLAVOR="-Zomf -Zcrtdll" RLLIBS=-lreadline_import DLLD_IGNORE= bench
+ cd ..
+
+The statically build PARI library is in a file named similar to libpari-2_2.a,
+the library for linking with the PARI DLL is named as pari-2_2.a (or
+pari-2_2.lib).
+
+As a debugging tool, the constructed DLL reports its build options via the
+standard OS/2 way:
+
+ bldlevel FULL_NAME_OF_THE_DLL