|C H A P T E R 4|
This chapter describes how to use and create libraries of subprograms. Both static and dynamic libraries are discussed.
A software library is usually a set of subprograms that have been previously compiled and organized into a single binary library file. Each member of the set is called a library element or module. The linker searches the library files, loading object modules referenced by the user program while building the executable binary program. See ld(1) and the Solaris Linker and Libraries Guide for details.
There are two basic kinds of software libraries:
Typical system libraries that have both static (.a) and dynamic (.so) versions are:
There are two advantages to the use of libraries:
Library files provide an easy way for programs to share commonly used subroutines. You need only name the library when linking the program, and those library modules that resolve references in the program are linked and merged into the executable file.
Summary information about library usage and loading can be obtained by passing additional options to the linker through the LD_OPTIONS environment variable. The compiler calls the linker with these options (and others it requires) when generating object binary files.
Using the compiler to call the linker is always recommended over calling the linker directly because many compiler options require specific linker options or library references, and linking without these could produce unpredictable results.
Example: Using LD_OPTIONS to create a load map:
Some linker options do have compiler command-line equivalents that can appear directly on the f95 command. These include -Bx, -dx, -G, -hname, -Rpath, and -ztext. See the f95(1) man pages or the Fortran User's Guide for details.
More detailed examples and explanations of linker options and environment variables can be found in the Solaris Linker and Libraries Guide.
The linker -m option generates a load map that displays library linking information. The routines linked during the building of the executable binary program are listed together with the libraries that they come from.
Example: Using -m to generate a load map:
Additional linker debugging features are available through the linker's -Dkeyword option. A complete list can be displayed using -Dhelp.
Example: List linker debugging aid options using the -Dhelp option:
For example, the -Dfiles linker option lists all the files and libraries referenced during the link process:
See the Linker and Libraries Guide for further information on these linker options.
Ensuring a consistent choice of compiling and linking options is critical whenever compilation and linking are done in separate steps. Compiling any part of a program with some options requires linking with the same options. Also, a number of options require that all source files be compiled with that option, including the link step.
The option descriptions in the Fortran User's Guide identify such options.
Example: Compiling sbr.f with -fast, compiling a C routine, and then linking in a separate step:
The linker searches for libraries at several locations and in a certain prescribed order. Some of these locations are standard paths, while others depend on the compiler options -Rpath, -llibrary, and -Ldir and the environment variable LD_LIBRARY_PATH.
The standard library search paths used by the linker are determined by the installation path, and they differ for static and dynamic loading. A standard install puts the Sun Studio compiler software under /opt/SUNWspro/.
While building the executable file, the static linker searches for any libraries in the following paths (among others), in the specified order:
These are the default paths used by the linker.
The dynamic linker searches for shared libraries at runtime, in the specified order:
The search paths are built into the executable.
Use the LD_LIBRARY_PATH environment variable to specify directory paths that the linker should search for libraries specified with the -llibrary option.
Multiple directories can be specified, separated by a colon. Typically, the LD_LIBRARY_PATH variable contains two lists of colon-separated directories separated by a semicolon:
The directories in dirlist1 are searched first, followed by any explicit -Ldir directories specified on the command line, followed by dirlist2 and the standard directories.
That is, if the compiler is called with any number of occurrences of -L, as in:
f95 ... -Lpath1 ... -Lpathn ...
then the search order is:
dirlist1 path1 ... pathn dirlist2 standard_paths
When the LD_LIBRARY_PATH variable contains only one colon-separated list of directories, it is interpreted as dirlist2.
In the Solaris operating environment, a similar environment variable, LD_LIBRARY_PATH_64 can be used to override LD_LIBRARY_PATH when searching for 64-bit dependencies. See the Solaris Linker and Libraries Guide and the ld(1) man page for details.
Note - Use of the LD_LIBRARY_PATH environment variable with production software is strongly discouraged. Although useful as a temporary mechanism for influencing the runtime linker's search path, any dynamic executable that can reference this environment variable will have its search paths altered. You might see unexpected results or a degradation in performance.
Use the -llibrary compiler option to name additional libraries for the linker to search when resolving external references. For example, the option -lmylib adds the library libmylib.so or libmylib.a to the search list.
The linker looks in the standard directory paths to find the additional libmylib library. The -L option (and the LD_LIBRARY_PATH environment variable) creates a list of paths that tell the linker where to look for libraries outside the standard paths.
Were libmylib.a in directory /home/proj/libs, then the option
-L/home/proj/libs would tell the linker where to look when building the executable:
For any particular unresolved reference, libraries are searched only once, and only for symbols that are undefined at that point in the search. If you list more than one library on the command line, then the libraries are searched in the order in which they are found on the command line. Place -llibrary options as follows:
The -Ldir option adds the dir directory path to the library search list. The linker searches for libraries first in any directories specified by the -L options and then in the standard directories. This option is useful only if it is placed preceding the
-llibrary options to which it applies.
With dynamic libraries, changing the library search path and order of loading differs from the static case. Actual linking takes place at runtime rather than build time.
When building the executable file, the linker records the paths to shared libraries in the executable itself. These search paths can be specified using the -Rpath option. This is in contrast to the -Ldir option which indicates at buildtime where to find the library specified by a -llibrary option, but does not record this path into the binary executable.
The directory paths that were built in when the executable was created can be viewed using the dump command.
Example: List the directory paths built into a.out:
At runtime, the linker determines where to find the dynamic libraries that an executable needs from:
As noted earlier, use of LD_LIBRARY_PATH can have unexpected side-effects and is not recommended.
When the dynamic linker cannot locate a needed library, it issues this error message:
ld.so: prog: fatal: libmylib.so: can't open file:
The message indicates that the libraries are not where they are supposed to be. Perhaps you specified paths to shared libraries when the executable was built, but the libraries have subsequently been moved. For example, you might have built a.out with your own dynamic libraries in /my/libs/, and then later moved the libraries to another directory.
Use ldd to determine where the executable expects to find the libraries:
If possible, move or copy the libraries into the proper directory or make a soft link to the directory (using ln -s) in the directory that the linker is searching. Or, it could be that LD_LIBRARY_PATH is not set correctly. Check that LD_LIBRARY_PATH includes the path to the needed libraries at runtime.
Static library files are built from precompiled object files (.o files) using the ar(1) utility.
The linker extracts from the library any elements whose entry points are referenced within the program it is linking, such as a subprogram, entry name, or COMMON block initialized in a BLOCKDATA subprogram. These extracted elements (routines) are bound permanently into the a.out executable file generated by the linker.
There are three main issues to keep in mind regarding static, as compared to dynamic, libraries and linking:
If you bind an a.out executable file statically, the library routines it needs become part of the executable binary. However, if it becomes necessary to update a static library routine bound into the a.out executable, the entire a.out file must be relinked and regenerated to take advantage of the updated library. With dynamic libraries, the library is not part of the a.out file and linking is done at runtime. To take advantage of an updated dynamic library, all that is required is that the new library be installed on the system.
Since a single compilation unit (a source file) can contain more than one subprogram, these routines when compiled together become a single module in the static library. This means that all the routines in the compilation unit are loaded together into the a.out executable, even though only one of those subprograms was actually called. This situation can be improved by optimizing the way library routines are distributed into compilable source files. (Still, only those library modules actually referenced by the program are loaded into the executable.)
The linker processes its input files in the order in which they appear on the command line--left to right. When the linker decides whether or not to load an element from a library, its decision is determined by the library elements that it has already processed. This order is not only dependent on the order of the elements as they appear in the library file but also on the order in which the libraries are specified on the compile command line.
Example: If the Fortran program is in two files, main.f and crunch.f, and only the latter accesses a library, it is an error to reference that library before crunch.f or crunch.o:
Suppose that you can distribute all the routines in a program over a group of source files and that these files are wholly contained in the subdirectory test_lib/.
Suppose further that the files are organized in such a way that they each contain a single principal subprogram that would be called by the user program, along with any "helper" routines that the subprogram might call but that are called from no other routine in the library. Also, any helper routines called from more than one library routine are gathered together into a single source file. This gives a reasonably well-organized set of source and object files.
Assume that the name of each source file is taken from the name of the first routine in the file, which in most cases is one of the principal files in the library:
The lower-level "helper" routines are gathered together into the file etc.f. The other files can contain one or more subprograms.
First, compile each of the library source files, using the -c option, to generate the corresponding relocatable .o files:
Now, create the static library testlib.a using ar:
To use this library, either include the library file on the compilation command or use the -l and -L compilation options. The example uses the .a file directly:
Notice that the main program calls only two of the routines in the library. You can verify that the uncalled routines in the library were not loaded into the executable file by looking for them in the list of names in the executable displayed by nm:
In the preceding example, grep finds entries in the list of names only for those library routines that were actually called.
Another way to reference the library is through the -llibrary and -Lpath options. Here, the library's name would have to be changed to conform to the libname.a convention:
The -llibrary and -Lpath options are used with libraries installed in a commonly accessible directory on the system, like /usr/local/lib, so that other users can reference it. For example, if you left libtestlib.a in /usr/local/lib, other users could be informed to compile with the following command:
It is not necessary to recompile an entire library if only a few elements need recompiling. The -r option of ar permits replacement of individual elements in a static library.
Example: Recompile and replace a single routine in a static library:
To order the elements in a static library when it is being built by ar, use the commands lorder(1) and tsort(1):
Dynamic library files are built by the linker ld from precompiled object modules that can be bound into the executable file after execution begins.
Another feature of a dynamic library is that modules can be used by other executing programs in the system without duplicating modules in each program's memory. For this reason, a dynamic library is also a shared library.
A dynamic library offers the following features:
Dynamic libraries introduce some additional tradeoff considerations:
Deferring binding of the library routines until execution time means that the size of the executable file is less than the equivalent executable calling a static version of the library; the executable file does not contain the binaries for the library routines.
When several processes using the library are active simultaneously, only one copy of the library resides in memory and is shared by all processes.
Additional processor time is needed to load and link-edit the library routines during runtime. Also, the library's position-independent coding might execute more slowly than the relocatable coding in a static library.
Reduced memory utilization due to library sharing should result in better overall system performance (reduced I/O access time from memory swapping).
Performance profiles among programs vary greatly from one to another. It is not always possible to determine or estimate in advance the performance improvement (or degradation) between dynamic versus static libraries. However, if both forms of a needed library are available to you, it would be worthwhile to evaluate the performance of your program with each.
Position-independent code (PIC) can be bound to any address in a program without requiring relocation by the link editor. Such code is inherently sharable between simultaneous processes. Thus, if you are building a dynamic, shared library, you must compile the component routines to be position-independent by using the -xcode compiler option.
In position-independent code, each reference to a global item is compiled as a reference through a pointer into a global offset table. Each function call is compiled in a relative addressing mode through a procedure linkage table. The size of the global offset table is limited to 8 Kbytes on SPARC processors.
Use the compiler flag -xcode=v for specifying the code address space of a binary object. With this flag, 32-, 44-, or 64-bit absolute addresses can be generated, as well as small and large model position-independent code. (-xcode=pic13 is equivalent to the legacy -pic flag, and -xcode=pic32 is equivalent to -PIC.)
The -xcode=pic32 compiler option is similar to -xcode=pic13, but allows the global offset table to span the range of 32-bit addresses. See the f95(1) man page or the Fortran User's Guide, for details.
You can specify dynamic or static library binding when you compile. These options are actually linker options, but they are recognized by the compiler and passed on to the linker.
-Bdynamic sets the preference for shared, dynamic binding whenever possible.
-Bstatic restricts binding to static libraries only.
When both static and dynamic versions of a library are available, use this option to toggle between preferences on the command line:
f95 prog.f -Bdynamic -lwells -Bstatic -lsurface
Allows or disallows dynamic linking for the entire executable. (This option may appear on the command line only once.)
-dy allows dynamic, shared libraries to be linked. -dn does not allow linking of dynamic libraries.
Some static system libraries, such as libm.a and libc.a, are not available on 64-bit Solaris operating environments. These are supplied as dynamic libraries only. Use of -dn in these environments will result in an error indicating that some static system libraries are missing. Also, ending the compiler command line with -Bstatic will have the same effect.
To link with static versions of specific libraries, use a command line that looks something like:
f95 -o prog prog.f -Bstatic -labc -lxyz -Bdynamic
Here the user's libabc.a and libxyz.a file are linked (rather than libabc.so or libxyz.so), and the final -Bdynamic insures that the remaining libraries, including system libraries, and dynamically linked.
In more complicated situations, it may be necessary to explicitly reference each system and user library on the link step with the appropriate -Bstatic or -Bdynamic as required. First use LD_OPTIONS set to '-Dfiles' to obtain a listing of all the libraries needed. Then perform the link step with -nolib (to suppress automatic linking of system libraries) and explicit references to the libraries you need. For example:
f95 -xarch=v9 -o cdf -nolib cdf.o -Bstatic -lsunmath \
-Bdynamic -lm -lc
To conform to the dynamic library naming conventions assumed by the link loader and the compilers, assign names to the dynamic libraries that you create with the prefix lib and the suffix .so. For example, libmyfavs.so could be referenced by the compiler option -lmyfavs.
The linker also accepts an optional version number suffix: for example, libmyfavs.so.1 for version one of the library.
The compiler's -hname option records name as the name of the dynamic library being built.
Building a dynamic library requires a compilation of the source files with the -xcode option and linker options -G, -ztext, and -hname. These linker options are available through the compiler command line.
You can create a dynamic library with the same files used in the static library example.
Example: Compile with -pic and other linker options:
-G tells the linker to build a dynamic library.
-ztext warns you if it finds anything other than position-independent code, such as relocatable text.
Example: Make an executable file a.out using the dynamic library:
Note that the example uses the -R option to bind into the executable the path (the current directory) to the dynamic library.
The file command shows that the executable is dynamically linked.
When building dynamic libraries, insure proper initialization of common blocks (by DATA or BLOCK DATA) by gathering the initialized common blocks into the same library, and referencing that library before all others.
The first compilation creates a dynamic library from files that define common blocks and initialize them in BLOCK DATA units. The second compilation creates the executable binary, linking the compiled main program with the dynamic libraries required by the application. Note that the dynamic library that initializes all the common blocks appears first before all the other libraries. This insures the blocks are properly initialized.
The table shows the libraries installed with the compilers.
If your executable uses a Sun dynamic library that is listed in the runtime.libraries README file, your license includes the right to redistribute the library to your customer.
This README file is located in the READMEs directory:
Do not redistribute or otherwise disclose the header files, source code, object modules, or static libraries of object modules in any form.
Refer to your software license for more details.