
SVR3 shared library building help kit version 1.4
----------------------------------------------------------------------------

Files
----------------------------------------------------------------------------

filename		purpose
-----------------------------------------------------------------------------
mkshtmpl.sh		This is a script to create the necessary description
XlibsMakefile		files from the respective archive library version,
sv3ShlibAddr		an auxiliary makefile used by the script and a file
			containing the address range definitions for the
			various X libraries.

chkimports.sh		This script is usefull to check a generated
			shared library for (incorrect) differences of the
			imported symbols to the archive version.

datasize		This is a small script which evaluates the size
			of the .data section of an archiv library.

libX11/addImports	These files containg explicit imported symbols
libXt/addImports	for libX11 and libXt. (They are examples.)

libX11/constData	These files containg data symbol definitions of
libXt/constData		(ANSI-C) constant data, which goes to .text section.
			To avoid that mkshtmpl.sh creates a bad branch
			entry table for such symbols they must be putted
			here. (The files are examples.)


			
Creating a shared library
-----------------------------------------------------------------------------
NOTE: 1. RTFM of your system!!!

      Mkshtmpl.sh script is not perfect. The files generated by mkshtmpl.sh
      must be edited by hand. On simple libraries (e.g. libXext) less, on
      complex libraries (e.g. libXaw) more. And more bad, in most cases
      you must make changes in the library sources.

      <lib> in the following description stands for libXm, libxview
      or whichever library do you want make shareable.


mkshtmpl.sh
-----------
Before you running the script you must do some things.
First list the address ranges of the shared library in sv3ShlibAddr if
they doesn't already exist.
Second think over whether you want reference symbols from other
shared libraries directly via the #object noload directive.
Then you have to choices: you can write a auxilary makefile similar
the included XlibsMakefile. Then mkshtmpl.sh will use it (you must edit
mkshtmpl.sh to put your filename in) and such symbols are removed
automatically from the generated description files.
Or you must do this by hand after running mkshtmpl.sh.

Third if you know some global "const"ant data symbols list them
in a file <lib>/constData. Check the sources for 
E.g. the file libX11/constData contains:

	evtomask.o D _Xevent_to_mask
	XStrKeysym.o D _XkeyTable

The "D" stands for "D"ata. The problem is that ANSI C compilers
put "const" data to .text section and hence mkshtmpl.sh generates
a bad branch table entry. The file overrides these symbols.

Second, if you want explicit import some symbols (e.g. from the
library itself) put these to a file <lib>/addImports.
E.g. the file libX11/addImports contains:

	100 XauDisposeAuth globals.o
	100 XauFileName globals.o
	100 XauGetBestAuthByAddr globals.o
	100 XauReadAuth globals.o

Although it is possible, you should not use something other than "100"
and "globals.o".
Then call with the path name of the respective archive library.
E.g.
	cd mit/util/mksv3shlib
	mkshtmpl.sh ../../lib/X/libX11.a

This creates at first a directory <lib> and within that the files <lib>.def,
<lib>.h and <lib>.c. <Lib>.def is the shared library description file in a
format to process it during building of the library with the preprocessor to
evaluate some defines (DOWN, __GNUC__) and it can contain two optional sections
"#externals" and "#libraries" which are used during the library built and
removed before mkshlib is called. (Compare with the rules in
mit/config/sv3Lib.rules.) <Lib>.h contains contains indirection #define's
and <lib>.c the definitions of the pointers.
(In addition two files <lib>/exports.out and <lib>/imports.out are created.
 These files are input files for chkimports.sh. See below.)

NOTE: The generated files need editing! Not all things are right. See
      also comments in the created files. 

Trying to build a shared library:
Copy <lib>.def, <lib>.h, <lib>.c in the <lib> source directory. Rename <lib>.h
to imports.h. If there is no other globals.c rename <lib>.c to globals.c, if
there is another globals.c put

#include "<lib>.c"

to it. Note, the needed guards:
#ifdef SVR3SHLIB
...
#endif
are inside <lib>.c. This is to get a dependence in the Makefile. 
List globals.c/globals.o in the Imakefile of the library under SRCS/OBJS or
whatever the respective variable names are called.
Put a special rule for globals.o in the Imakefile (best after
LibraryObjectRule(), Imakefile:

...
LibraryObjectRule()

#if defined(i386SVR3Architecture) && DoSharedLib
SpecialLibObjectRule(globals.o,$(ICONFIGFILES),-D_libXext_import)
#endif
...


Be aware that you must probably also change source files of the library.
(See Hints).


chkimports.sh
-------------

This scripts checks whether a created shared library imports other symbols
then the archive version and vice versa. I wrote it to find mean errors
caused by double used names (like syscall "stat" and structure "stat")
and a certain style of extern declarations, like:
...
char *
XauFileName ()
{
    char    *name, *malloc (), *getenv ();
    char    *strcat (), *strcpy ();
...
Very bad if we want "#define malloc  (*_libX11_malloc)" ...
Check the sources for that! All what you must do is putting the friendly
word "extern" before the function declaration. Otherwise this causes
mysterious core dumps.

The script needs <lib>/exports.out and <lib>/imports.out previously generated
by mkshtmpl.sh and of course a created shared library.
E.g.
	chkimports.sh ../../lib/X/libX11_s.a

If there are errors printed out these are probably really errors. Probably you
get also a lot of warnings. Most of them come from globals.o, ignore them.
Check the others exactly. E.g. if our nice gcc 2.x.x optimizes it uses some-
times its in-built strcmp(3)/strcpy(3). But if it's redefined e.g.
"_libX11_strcmp" gcc don't do it and therefore there is difference between
the archive and the shared version. We could ignore it but for performance
its better to put following to the appropriate source file:

(e.g.)

#if defined(SVR3SHLIB) && (__GNUC__ == 2) && defined(__OPTIMIZE__)
#undef strcmp
#endif

Other differences come from declarations of external functions without the
keyword "extern". Due to redefinition these symbols become pointer definitions.
They are uninitialized and hence the compiler create common symbols (which
cause the warnings of the script). But since they are common this is no
problem. Ignore them. Prime candidats are: gethostbyname and other stuff from
BSD style headers, XauDisposeAuth, XauFileName, XauGetBestAuthByAddr,
XauReadAuth.

Remaining warnings could be real errors.


Hints
-----

If the library is simple and has less global data you don't must change
much in the automatically generated files. But you should care to put
global data to the top of the shared library, to avoid breaking
clients if you replace the target shared lib in the future.

If you have big data in some less used objects in the library you can
seperate it from the code in put it only to the host shared library.
The advantage is that this data goes only to clients which really
needs it instead to the data section of the shared lib which is
copied for every client.
But there is also a big disadvantage. If a future library version changes
its internal data structures the client will break. (One example
for that is libXaw and libXaw3d.)
But to do it you must split the respective source file with #ifdefs.
There are predifined defines for that.
E.g. foo.c:

...

#if !defined(SVR3SHLIB) || defined(SVR3SHDAT)
...
struct HugeStruct huge_struct = {0};
char mega[1024*1024] = "";

#endif

#ifndef SVR3SHDAT
extern struct HugeStruct huge_struct;
extern char mega[];
...

int foo() { 
...
};

...
#endif

The imake rules are prepared to compile such sources twice, if you are list
them in the Imakefile twice (one time with suffix .sd), Imakefile:
...
OBJS = \
	foo.o \
	...
	foo.sd
...
The .sd file will contain the data. To put it in the host shared library
you must list it in the #externals section of <lib>.def:
...
/**/externals
foo.sd


Note, actually this method is not used with the X libraries, because
of the above mentioned disadvantage.
















