[comp.unix.aix] Making shared libraries

schorr@ead.dsa.com (Andrew J. Schorr) (10/12/90)

My question is simple: how do you make shared libraries?
As I understand it, the process is as follows:

  1. compile the source into .o files as you would normally;
     are there any special compiler flags required here?
     I don't seem to see anything analogous to -pic on a Sun.

  2. create an export list for the library;
     I'm using nm to make it automatically as follows:
	nm -g {object files} | \
	awk '$(NF-1) == "D" {print $NF}' > export.list

  3. link the .o files into a shared object as follows:
	ld -r -o shared_object.o {object files} -bE:export.list \
		-bM:SRE -T512 -H512

  4. insert the resulting shared_object.o into an archive (if so desired)

Everything seems to work, but when I run a program linked against
the library, I get the following messages:

   Could not load program test_program 
   Could not load library libtest.0.1.a[shared_object.o]
   Error was: No such file or directory

Apparently, the loader can't find the library at run-time.  How
do you tell it where to look?  It seems that this might involve
putting a special line in the export.list that starts with #!, 
but I'm not sure exactly.  Can someone help me?  The ld man page
is very vague on this subject.

Thanks in advance,
Andy 

wlm@arnor.uucp (10/15/90)

Well, I think there are several ways of doing what you want.

First, shared things are looked for in /usr/lib and /lib (I forget the
order), so if you put that lib in one of those places, the system
will find it.

Second, I seem to recall that there is something like LIBPATH looked
for by the linker, and it looks in the places named. I don't recall
whether you have to say:
setenv LIBPATH
/lib:/usr/lib:/a/aragorn/homes/aragorn1/src/X11R4-new/mit/new-lib/X
or whether
setenv LIBPATH /a/aragorn/homes/aragorn1/src/X11R4-new/mit/new-lib/X is
sufficient.

Third, at link time, you can do something like:

cc -o ico -O ico.o
/a/aragorn/homes/aragorn1/src/X11R4-new/mit/new-lib/X/shared.\
o -L/a/aragorn/homes/aragorn1/src/X11R4-new/mit/new-lib/X -lm

where shared.o is a shared version of the R4 libX11.a. Using the -L flag
puts info in the load header of the resulting executable which allows
the loader to find the shared part when you try to run it.

Finally, there probably is a #![...] directive for the export file,
but I can't find the documentation for that stuff at the moment.

I would suggest judicious use of -L.

Bill Moran

bengsig@oracle.nl (Bjorn Engsig) (10/15/90)

Article <1990Oct11.160027@ead.dsa.com> by schorr@ead.dsa.com (Andrew J. Schorr) says:
|My question is simple: how do you make shared libraries?
If you read the ld man page carefully between the lines, you will see that
in your step 3:
|  3. link the .o files into a shared object as follows:
|	ld -r -o shared_object.o {object files} -bE:export.list \
|		-bM:SRE -T512 -H512
you are not allowed to use -r, but you should add -lc (plus anything else
needed) to create a fully linked object without unresolved references.
|  The ld man page
|is very vague on this subject.
Indeed.
-- 
Bjorn Engsig,         E-mail: bengsig@oracle.com, bengsig@oracle.nl
ORACLE Corporation    From IBM: auschs!ibmaus!cs.utexas.edu!uunet!oracle!bengsig

            "Stepping in others footsteps, doesn't bring you ahead"

frank@gremlin.austin.ibm.com (Frank Feuerbacher) (10/16/90)

In article <1990Oct11.160027@ead.dsa.com>, schorr@ead.dsa.com (Andrew J.
Schorr) writes:

> My question is simple: how do you make shared libraries?
>
>   1. compile the source into .o files as you would normally;
>      are there any special compiler flags required here?

  No, there are no special flags.

>      I don't seem to see anything analogous to -pic on a Sun.
>
>   2. create an export list for the library;
>      I'm using nm to make it automatically as follows:
>       nm -g {object files} | \
>       awk '$(NF-1) == "D" {print $NF}' > export.list

If this gets you a list of all symbols (code & data) that is defined in these
object files that you want to export, then this is correct.  Here is what
I have used: (Its slower, but it works)
  First archive all .o's into scratch.a
  then,
    nm scratch.a | egrep 'extern.*((\.text$$)|(\.data$$)|(\.bss$$))'
>shared.syms
    sed "s/[        ]*\|.*//g" shared.syms >shared.exports
    sed "s/^\.//g" shared.exports | sort | uniq >shared.exp
    rm -f shared.syms shared.exports

>
>   3. link the .o files into a shared object as follows:
>       ld -r -o shared_object.o {object files} -bE:export.list \

This looks okay, but if shared_object.o references things like libc, then
you would want to add "-lc" to this.
        -bM:SRE -lc

>
>   4. insert the resulting shared_object.o into an archive (if so desired)
>
> Everything seems to work, but when I run a program linked against
> the library, I get the following messages:
>
>    Could not load program test_program
>    Could not load library libtest.0.1.a[shared_object.o]
>    Error was: No such file or directory
>
> Apparently, the loader can't find the library at run-time.  How
> do you tell it where to look?  It seems that this might involve
> putting a special line in the export.list that starts with #!,
> but I'm not sure exactly.  Can someone help me?  The ld man page
> is very vague on this subject.

First #! lines don't belong in export lists, they go with import lists.
The import list tells the binder that the listed symbols are to be
resolved at execution time.  The #! gives the path & member name of the
library that the loader should find these symbols in.  I can't quite remember
what the default path rules are.

In your case, you don't seem to need an import file, so you don't need the #!
line.

When you bind with a shared library, I believe that the bound object remembers
the path to the shared library.  I believe that the LIBPATH environment
variable is also used in the event that the library is not found there.  You
might want to look at the documentation on 'exec' or 'load' subroutine calls.

As a final note, one important thing that people tend to miss is that
a shared library MUST NOT refer to a symbol that is defined outside of a
shared library (i.e. a shared library must not refer to a function or data
object that is defined outside of a shared library).

I hope this helps a little bit, and that I have not made any mistakes.

- Frank Feuerbacher


Disclaimer: I don't speak for my employer and they don't speak for me.