HP-UX Linker and Libraries User's Guide

$ cc -Aa -c +z length.c Make new length.o.
$ ld -b -o libunits.sl oldlength.o \ Relink the library.
volume.o mass.o length.o
Thereafter, any programs linked with libunits.sl use the new versions of length-conversion
routines defined in length.o. Programs linked with the old version of the library still use those
routines from oldlength.o. For details on linking with shared libraries, see“Determining How
to Link Programs or Libraries (Linker Tasks)” (page 27).
Specifying a Version Date
When adding modules to a library for a particular release of the library, it is best to give all
modules the same version date. For example, if you complete file1.o on 04/93, file2.o
on 05/93, and file3.o on 07/93, it is best to give all the modules the same version date,
say 07/93.
The reason for doing this is best illustrated with an example. Suppose in the previous example you
gave each module a version date corresponding to the date it was completed: 04/93 for file1.o,
05/93 for file2.o, and 07/93 for file3.o. You then build the final library on 07/93
and link an application a.out with the library. Now suppose that you introduce an incompatible
change to function foo found in file1.o, set the version date to 05/93, and rebuild the library.
If you run a.out with the new version of the library, a.out gets the new, incompatible version
of foo because its version date is still earlier than the date the application was linked with the
original library.
Switching from Archive to Shared Libraries
There are cases where a program may behave differently when linked with shared libraries than
when linked with archive libraries. These are the results of subtle differences in the algorithms the
linker uses to resolve symbols and combine object modules. This section covers these considerations.
(See also “Caution When Mixing Shared and Archive Libraries (page 118) .)
Relying on Undocumented Linker Behavior
Occasionally, programmers may take advantage of linker behavior that is undocumented but has
traditionally worked. With shared libraries, such programming practices may not work or may
produce different results. If the old behavior is absolutely necessary, linking with archive libraries
alone (-a archive) produces the old behavior.
For example, suppose several definitions and references of a symbol exist in different object and
archive library files. By specifying the files in a particular link order, you can cause the linker to
use one definition over another. But doing so requires an understanding of the subtle (and
undocumented) symbol resolution rules used by the linker, and these rules are slightly different for
shared libraries. So make files or shell scripts that took advantage of such linker behavior prior to
the support of shared libraries may not work as expected with shared libraries.
More commonly, programmers may take advantage of undocumented linker behavior to minimize
the size of routines copied into the a.out files from archive libraries. This is no longer necessary
if all libraries are shared.
Although it is impossible to characterize the new resolution rules exactly, the following rules always
apply:
1. If a symbol is defined in two shared libraries, the definition used at run time is the one that
appeared first regardless of where the reference was.
2. The linker treats shared libraries more like object files.
As a consequence of the second rule, programs that call wrapper libraries may become larger.
(A wrapper library is a library that contains alternate versions of C library functions, each of which
performs some bookkeeping and then calls the actual C function. For example, each function in
the wrapper library may update a counter of how many times the actual C routine is called.) With
archive libraries, if the program references only one routine in the wrapper library, then only the
Switching from Archive to Shared Libraries 115