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:
The object modules are not bound into the executable file by the linker during the compile-link sequence; such binding is deferred until runtime.
A shared library module is bound into system memory when the first running program references it. If any subsequent running program references it, that reference is mapped to this first copy.
Maintaining programs is easier with dynamic libraries. Installing an updated dynamic library on a system immediately affects all the applications that use it without requiring relinking of the executable.
Dynamic libraries introduce some additional tradeoff considerations:
Smaller a.out file
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.
Possibly smaller process memory utilization
When several processes using the library are active simultaneously, only one copy of the library resides in memory and is shared by all processes.
Possibly increased overhead
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.
Possible overall system performance improvement
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.
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
–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 -m64 -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:
demo% f95 -o libtestlib.so.1 -G -xcode=pic13 -ztext \ –hlibtestlib.so.1 *.f
Example: Make an executable file a.out using the dynamic library:
demo% f95 -o trylib -R”pwd” trylib.f libtestlib.so.1 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 libfui.so.1 => /opt/SUNWspro/lib/libfui.so.1 libfai.so.1 => /opt/SUNWspro/lib/libfai.so.1 libc.so.1 => /usr/lib/libc.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.
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.
demo% f95 -G -xcode=pic32 -o init.so blkdat1.f blkdat2.f blkdat3.f demo% f95 -o prog main.f init.so otherlib1.so otherlib2.so
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.