It's very easy to build a Shared Library on Solaris (and *nix in general). However, the Solaris link-editor (/usr/ccs/bin/ld)has quite a few options. It can sometimes be very confusing to determine which options to use. Some of the general rules are outlined here:
Let the compiler do the work
First - do not invoke the link-editor (/usr/ccs/bin/ld) directly, instead run it via your compiler driver (cc/gcc/CC/g++). The compiler driver will include many magic files (crt*.o, values-xa.o, ...) which are important to the construction of your shared library. If you invoke the link-editor directly you will likely miss those files and the benefits they give you. The first thing that will fail if you drop the comiler supplied files is that your _init and _fini routines will not run when the shared library is loaded.
Use PIC code
Compile code destined for the shared library as Position Independent Code. You do this by using the cc -Kpic or gcc -fpic options, depending upon which compiler you are using. PIC code is the most flexible and efficient code for a shared library because it permits the final library to be loaded at any address in memory without having to be modified at run-time. This permits the sharing of the library among all processes which have loaded it on a given system - hence the name Shared Library. If you include non-PIC code in a shared library, it will still run but you loose the share ability of the library. You can enforce that all code in the shared object is PIC by adding the -z text option to your link line.
List your dependencies
Always list all of your libraries dependencies (what you link against) when building the shared library. By listing them at link-edit time the built library will have recorded in it what libraries it needs at run-time. You can enforce this at build time by adding the -z defs option to your link line.
Include the proper RunPaths
By default the run-time linker (ld.so.1) will always search /lib & /usr/lib (or /lib/64 & /usr/lib/64 for 64bit processes) to find a shared library at run-time. If your library is referencing objects not in those directories you must also include a RunPath to find the dependencies. This is done by adding a -R {path} for each directory containing a shared libraries being referenced by the current object being built. You should not depend upon LD_LIBRARY_PATH being set at run-time to find shared libraries. Applications and dependencies can be built to include a runpath using ld(1), and the -R option. This path is used to search for the dependencies of the object in which the runpath is recorded. If the dependencies are not in a constant location, use the $ORIGIN token as part of the pathname
Example
Following is a example link demonstrating all of the options that were recommended above
% cc -Kpic bar.c -G -o bar.so -z text -z defs -L /tmp/play/lib -R /tmp/play/lib -lfoo -lc
% ldd -r bar.so
libfoo.so.1 => /tmp/play/lib/libfoo.so.1
libc.so.1 => /lib/libc.so.1
/platform/SUNW,Sun-Blade-1000/lib/libc_psr.so.1
libm.so.2 => /lib/libm.so.2
%
Note that you can use ldd to verify that your shared library is self contained and that it has the proper RunPath's defined. If either of those hadn't been true then ldd would have given appropriate error messages
Acknowledgements:
Michael Walker & Rod Evans of Sun Microsystems