Previous Next Contents Index Doc Set Home


Libraries

4


This chapter describes how to use and create libraries of subprograms. Both static and dynamic libraries are discussed.


Understanding Libraries

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 Sun Linker and Libraries Guide for details.

There are two basic kinds of software libraries:

Typical system libraries that have both static and dynamic versions are:

Advantages 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.

There are two advantages to the use of libraries:


Linker Debugging Options

Summary information about library usage and loading can be obtained by passing additional options to the linker on the compile command line, either by using the option syntax -Qoption ld linker_option or by setting the environment variable LD_OPTIONS.

Using LD_OPTIONS environment variable:

demo% setenv LD_OPTIONS "-m -Dfiles"
demo% f77 -o myprog myprog.f

is equivalent to:

demo% f77 -o myprog -Qoption ld -m -Qoption ld -Dfiles myprog.f

Some linker options have their compiler command-line equivalents and can appear directly on the f77 or f90 command: -Bx, -dx, -G, -hname,
-R
path, and -ztext.

More detailed examples and explanations of linker options and environment variables can be found in the Solaris Linker and Libraries Guide.

Generating a Load Map

The linker -m option generates a load map that displays library linking information listing the routines linked during the building of the executable binary program. Routines are listed together with the libraries that they come from.

Example: -m for load map:

demo% f77 -Qoption ld -m any.f
any.f:
 MAIN:
		LINK EDITOR MEMORY MAP


output		input			virtual
section		section			address			size

.interp 			   		100d4	      11
		.interp 	   100d4	      11 (null)
.hash   			   		100e8	     2e8
		.hash   	   100e8	     2e8 (null)
.dynsym 			   		103d0	     650
		.dynsym 	   103d0	     650 (null)
.dynstr 			   		10a20	     366
		.dynstr 	   10a20	     366 (null)
.text   			   		10c90		  1e70
		.text   	   10c90	      00 /set/lang/sparc-S2/SC4.2/lib/crti.o
		.text   	   10c90	      f4 /set/lang/sparc-S2/SC4.2/lib/crt1.o
		.text   	   10d84	      00 /set/lang/sparc-S2/SC4.2/lib/values-xi.o
		.text   	   10d88	     d20 sparse.o
...etc

Listing Other Information

Solaris 2.3 and later has additional linker debugging features, available through the linker's -Dkeyword option. A complete list can be displayed using -Dhelp.

Example: List linker debugging aid options using -Dhelp option:

demo% ld -Dhelp
	...
debug: args	     display input argument processing
debug: bindings	 display symbol binding; 
debug: detail	   provide more information 
debug: entry	    display entrance criteria descriptors
	...
demo%

For example, the -Dfiles linker option lists all the files and libraries referenced during the link process:



demo% f77 -Qoption ld -Dfiles direct.f
direct.f:
 MAIN direct:
debug: file=/opt/SUNWspro/SC4.2/lib/crti.o  [ ET_REL ]
debug: file=/opt/SUNWspro/SC4.2/lib/crt1.o  [ ET_REL ]
debug: file=/opt/SUNWspro/SC4.2/lib/values-xi.o  [ ET_REL ]
debug: file=direct.o  [ ET_REL ]
debug: file=/opt/SUNWspro/SC4.2/lib/libM77.a  [ archive ] 
debug: file=/opt/SUNWspro/lib/libF77.so  [ ET_DYN ]
debug: file=/opt/SUNWspro/SC4.2/lib/libsunmath.a  [ archive ] 
	...

See the Linker and Libraries Guide for further information on these linker options.

Consistent Compiling and Linking

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 any of the following options requires linking with the same options:

-a, -autopar, -cg92, -dalign, -dbl, -explicitpar, -f,
-fast, -misalign, -p, -parallel, -pg, -r8, -xarch=a, -xcache=c, -xchip=c, xprofile=p, -xtarget=t, -Zlp, -Ztha

Example: Compiling sbr.f with -a and smain.f without it, then linking in separate steps (-a invokes tcov old-style profiling):

 demo% f77 -c -a sbr.f       
 demo% f77 -c smain.f
 demo% f77 -a sbr.o smain.o   {pass -a to the linker}


Library Search Paths and Order

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.

Search Order for Standard Library Paths

The standard library search paths used by the linker are determined by the installation path, and they differ for static and dynamic loading.

The base directory, here called BaseDir, is defined as follows:


Standard Install
Nonstandard Install to /my/dir/
BaseDir =

/opt/SUNWspro/

/my/dir/SUNWspro/

Static Linking

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.

Dynamic Linking

The dynamic linker searches for shared libraries at runtime, in the specified order:

The search paths are built into the executable.

Library Search Path and Order -- Static Linking

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:

demo% f77 -o pgram part1.o part2.o -L/home/proj/libs -lmylib

Command-Line Order for -llibrary Options

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 they are found on the command line. Place -llibrary options as follows:

Command-Line Order for -Ldir Options

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.

LD_LIBRARY_PATH Environment Variable

Use the environment variable LD_LIBRARY_PATH to specify directory paths the linker should search for libraries specified with the -llibrary option. Using this environment variable would make the previous example look like:

demo% setenv LD_LIBRARY_PATH /home/proj/libs
demo% f77 -o pgram part1.o part2.o -lmylib

Multiple directories can be specified, separated by a colon. In the most general case, the LD_LIBRARY_PATH variable may contain two lists of colon-separated directories separated by a semicolon:

dirlist1;dirlist2

The directories in dirlist1 are searched first, followed by any explicit -Ldir directories specified on the command line, followed then by dirlist2 and the standard directories.

That is, if the compiler is called with any number of occurrences of -L, as in:

f77 ... -Lpath1 ... -Lpathn ...

then the search ordering is:

dirlist1 path1 ... pathn dirlist2 standard_paths

When the LD_LIBRARY_PATH variable contains only a single colon-separated list of directories, it is interpreted as dirlist2.


Note - Use of this 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, which could cause unexpected results or a degradation in performance.

Library Search Path and Order -- Dynamic Linking

Changing the library search path and order of loading with dynamic libraries differs from the static case in that actual linking takes place at runtime rather than build time.

Specifying Dynamic Libraries at Build Time

When building the executable file, the linker records the paths to shared libraries into the executable itself. These search paths can be specified by using the -Rpath option. (Contrast with the -Ldir option which indicates where at buildtime 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:

demo% f77 program.f -R/home/proj/libs -L/home/proj/libs -lmylib
demo% dump -Lv a.out | grep RPATH   
[5]	RPATH    /home/proj/libs:/opt/SUNWspro/lib

Specifying Dynamic Libraries at Runtime

At runtime, the linker determines where to find the dynamic libraries an executable needs from:

As noted earlier, use of LD_LIBRARY_PATH can have unexpected side-effects and is not recommended.

Errors During Dynamic Linking

When the dynamic linker cannot locate a needed library, it issues the error message:

ld.so: prog: fatal: libmylib.so: can't open file: 
The possible causes might be:

Perhaps you specified paths to shared libraries when the executable was built, but the libraries have subsequently been moved. For example, you built a.out with your own dynamic libraries in /my/libs/, and then sometime later moved the libraries to another directory.

Use ldd to determine where the executable expects to find the libraries:

demo% ldd a.out
	libsolib.so =>	 /export/home/proj/libsolib.so
	libF77.so.3 =>	 /opt/SUNWspro/lib/libF77.so.3
	libc.so.1 =>	 /usr/lib/libc.so.1
	libdl.so.1 =>	 /usr/lib/libdl.so.1

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.

Check that LD_LIBRARY_PATH at runtime includes the path to the needed libraries.


Creating Static Libraries

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.

Tradeoffs

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 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 the Sun Performance Library library, it is an error to reference that library before crunch.f or crunch.o:

demo% f77 main.f -lsunperf crunch.f -o myprog 	        (Incorrect)
demo% f77 main.f crunch.f -lsunperf -o myprog	         (Correct)

Creation of a Simple Static Library

Suppose that we 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 may call but which 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:

demo% cd test_lib
demo% ls
total 14          2 dropx.f      2 evalx.f      2 markx.f
   2 delte.f      2 etc.f        2 linkz.f      2 point.f

The lower-level "helper" routines are gathered together into the file etc.f. The other files may contain one or more subprograms.

First, compile each of the library source files, using the -c option, to generate the corresponding relocatable .o files:

demo% f77 -c *.f
delte.f:
    delte:
    q_fixx:
dropx.f:
    dropx:
etc.f:
    q_fill:
    q_step:
    q_node:
    q_warn:
 ...etc
demo% ls
total 42   
 2 dropx.f     4 etc.o      2 linkz.f    4 markx.o   
 2 delte.f      4 dropx.o     2 evalx.f     4 linkz.o     2 point.f
 4 delte.o       2 etc.f        4 evalx.o      2 markx.f      4 point.o
demo%

Now, create the static library testlib.a using ar:

demo% ar cr testlib.a *.o

To use this library, either include the library file on the compilation command or use the -l and -L compilation options.

Using the .a file directly:

demo% cat trylib.f
C    program to test testlib routines
		x=21.998
		call evalx(x)
		call point(x)
		print*, 'value ',x
		end
demo% f77 -o trylib trylib.f test_lib/testlib.a
trylib.f:
 MAIN:
demo%

Notice that the main program only calls 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:

demo% nm trylib | grep FUNC | grep point
[146]	|     70016|     152|FUNC |GLOB |0    |8      |point_
demo% nm trylib | grep FUNC | grep evalx
[165]	|     69848|     152|FUNC |GLOB |0    |8      |evalx_
demo% nm trylib | grep FUNC | grep delte
demo% nm trylib | grep FUNC | grep markx
demo% ..etc

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:

demo% mv test_lib/testlib.a test_lib/libtestlib.a
demo% f77 -o trylib trylib.f -Ltest_lib -ltestlib
trylib.f:
 MAIN:

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:

demo% f77 -o myprog myprog.f -L/usr/local/lib -ltestlib

Replacement in a Static Library

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:

demo% f77 -c point.f 
demo% ar r testlib.a point.o 
demo%

Ordering Routines 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):

demo% ar cr mylib.a 'lorder exg.o fofx.o diffz.o | tsort'


Creating Dynamic Libraries

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:

Tradeoffs

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 memory 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 may 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 and -pic

Position-independent code (PIC) is code that 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 compiler options -pic or -PIC).

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 8Kbytes on SPARC processors. The
-PIC
compiler option is similar to -pic, but -PIC allows the global offset table to span the range of 32-bit addresses.

Binding Options

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 | -Bstatic

-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:

f77 prog.f -Bdynamic -lwells -Bstatic -lsurface

-dy | -dn

Allows or disallows dynamic linking for the entire executable. (This option may appear only once on the command line.)

-dy allows dynamic, shared libraries to be linked. -dn does not allow linking dynamic libraries.

Naming Conventions

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 then 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, etc.

The compiler's -hname option records name as the name of the dynamic library being built.

A Simple Dynamic Library

Building a dynamic library requires a compilation of the source files with the
-pic or -PIC 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

demo% f77 -o libtestlib.so.1 -G -pic -ztext -hlibtestlib.so.1 *.f
delte.f:
	delte:
	q_fixx:
dropx.f:
	dropx:
etc.f:
	q_fill:
	q_step:
	q_node:
	q_warn:
evalx.f:
	evalx:
linkz.f:
	linkz:
markx.f:
	markx:
point.f:
	point:
Linking:

:

-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: Bind--make an executable file a.out using the dynamic library:

demo% f77 -o trylib -R`pwd` trylib.f libtestlib.so.1 
trylib.f:
 MAIN main:
demo% file trylib
trylib:		ELF 32-bit MSB executable SPARC Version 1, dynamically 
linked, not stripped
demo% ldd trylib
	libtestlib.so.1 =>	 /export/home/U/Tests/libtestlib.so.1
	libF77.so.3 =>	 /opt/SUNWspro/lib/libF77.so.3
	libc.so.1 =>	 /usr/lib/libc.so.1
	libdl.so.1 =>	 /usr/lib/libdl.so.1

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.

The ldd command shows that the executable, trylib, uses some shared libraries, including our libtestlib.so.1; libf77, libdl, and libc are included by default by f77. It also shows exactly which files on the system are used for these libraries.


Libraries Provided with Sun Fortran Compilers

Table 4-1 shows the libraries are installed with the compilers:

Table  4-1 Major Libraries Provided With the Compilers

Library
Name
Options Needed

f77 functions, nonmath

libF77

None

f77 functions, nonmath, multithread safe

libF77_mt

-parallel

f77 math library

libM77

None

VMS library

libV77

-lV77

Library used with Pascal, Fortran, and C

libpfc

None

Library of Sun math functions

libsunmath

None

POSIX bindings

libFposix

-lFposix

POSIX bindings for extra runtime checking

libFposix_c

-lFposix_c

XView bindings and Xlib bindings
for the X11 interface

libFxview

-lFxview
-lxview
-lX11

See also the math_libraries README file for more information.

VMS Library

The libV77 library is the VMS library, which contains two special VMS routines, idate and time.

To use either of these routines, include the -lV77 option.

For idate and time, there is a conflict between the VMS version and the version that traditionally is available on UNIX operating systems. If you use the -lV77 option, you get the VMS compatible versions of the idate and time routines.

See the Fortran Library Reference and the Fortran 77 Language Reference for details on these routines.

POSIX Library

There are two versions of POSIX bindings provided with the compilers:

If you pass bad handles:

Of course, the checking is time-consuming, and libFposix_c is several times slower.

Both POSIX libraries come in static and dynamic forms.

The POSIX bindings provided are for IEEE Standard 1003.9-1992.

IEEE 1003.9 is a binding of 1003.1-1990 to FORTRAN (X3.8-1978).

POSIX.1 documents:

To find out precisely what POSIX is, you need both the 1003.9 and the POSIX.1 documents.


Shippable Libraries

If your executable uses a Sun dynamic library that is listed in the following README file, your license includes the right to redistribute the library to your customer.

Standard install

/opt/SUNWspro/READMEs/runtime.libraries

Install to /my/dir/

/my/dir/SUNWspro/READMEs/runtime.libraries

Do not redistribute or otherwise disclose the header files, source code, object modules, or static libraries of object modules in any form.

Refer to the section, "License to Use," in the document, "End User Object Code License," at the back of the plastic case that contains the CD-ROM.


Previous Next Contents Index Doc Set Home