In a dynamic program, an actor can link a dynamic or shared library explicitly during its execution. This on-demand object linking has several advantages:
By processing a dynamic object when it is required rather than during the initialization of an application, start-up time can be greatly reduced. In fact, the object might not be required if its services are not required during a particular run of the application.
The application can choose between several different dynamic objects depending on the exact services required. For example, if different libraries implement the same driver interface, the application can choose a specific driver implementation and load it dynamically.
Any dynamic object added to the actor address space during execution can be freed after use, thereby reducing overall memory consumption.
Typically, an application performs the following sequence to access an additional dynamic object using the dynamic library API:
A dynamic object is located and added to the address space of a running application using dlopen(). Any dependencies this dynamic object has are also located and added at this time.
The added dynamic object and its dependencies are relocated, and any initialization sections within these objects are called.
The application locates symbols within the added objects using dlsym(). The application is then able to reference the data or call the functions defined by these new symbols.
After the application has finished with the objects, the address space can be freed using dlclose(). Any termination section within the objects being freed will be called at this time.
Any error conditions that occur as a result of using these runtime linker interface routines can be displayed using dlerror().
Both dynamic and shared libraries can be used in dynamic programs. The only difference is that shared libraries are not duplicated in memory.
The following imake macro is used to build dynamic libraries:
DynamicLibraryTarget(dlib, objs, staticLibs, dynamicLibs, dlDeps, options)
This macro includes the following arguments:
dlib: name of the resulting dynamic library (suffixed by .so).
objs: library components. A list of binary object files (suffixed by .o).
staticLibs: a list of the static libraries (.a) that can be statically linked.
dynamicLibs: a list of dependencies. This list includes the dynamic libraries that must be loaded together with the resulting library. Each library can be defined in one of two ways:
-L path -l name
On the host, the linker looks for the library path/libname.so. On the target, the runtime linker looks for lib name.so in the library search path.
path
This library path can be absolute or relative and is used on the host by the linker, and on the target by the runtime linker. A relative path containing a "/" is interpreted as relative to the current directory by the runtime linker. A path without the "/" is searched in the library search path by the runtime linker.
dlDeps: a list of dynamic libraries on which the resulting library depends. If these dynamic libraries are changed, the resulting library dlib will be rebuilt. Each library must be defined as a path on the host. Generally dlDeps duplicates the libraries described in dynamicLibs. To express the dependency without embedding a path in the executable, use the -L path -l name syntax.
options: any linker options.
The following example builds a dynamic library named libfoo.so from the binary objects files a.o and b.o. When this library is loaded dynamically, the runtime linker will also load the dynamic library libdyn.so, which must be in its search path.
DynamicLibraryTarget( libfoo.so, a.o b.o, , libdyn.so, , )
Dynamic libraries are supported with the gcc
compiler only.
The following imake macros are used to build dynamic applications:
DynamicUserTarget(prog, objs, staticLibs, dynamicLibs, dlDeps, options) DynamicSupTarget(prog, objs, staticLibs, dynamicLibs, dlDeps, options) DynamicCXXUserTarget(prog, objs, staticLibs, dynamicLibs, dlDeps, options) DynamicCXXSupTarget(prog, objs, staticLibs, dynamicLibs, dlDeps, options)
For details of the functions that each macro performs, refer to "imake Build Rules".
The prog argument is the name of the resulting process. Other arguments are similar to those in the DynamicLibraryTarget() macro. For the options argument, the following options are particularly useful:
-soname=<name>
Within a DynamicLibraryTarget() rule, this option sets the internal soname of the library. If a library is used as a dependency in a rule that builds a dynamic executable and has a soname defined, the executable records the soname instead of the dynamicLibs argument.
-rpath <dir>
This option defines the runpath directory that is added to the library search path.
The following example builds a dynamic application called dyn_app from the binary object files a.o and b.o. The process is statically linked with the static ChorusOS operating system library. When this application is started, the runtime linker loads the dynamic library libdyn.so. In the target file system, this library can be located in the /libraries directory because this directory will be added to the search path of the runtime linker.
DynamicUserTarget( dyn_app, a.o b.o, , libdyn.so, , -rpath /libraries)
The following imake macro is used to build shared libraries:
SharedLibraryTarget(shlib, shobjs, sharedLibs, staticLibs, slDeps, options)
shlib: the name of the resulting shared library (suffixed by .so).
shobjs: a list of binary object files in PIC format (suffixed by .o).
sharedLibs: a list of dependencies. This includes the shared libraries that must be loaded together with the resulting library. Each library can be defined in one of two ways:
-L path -l name
On the host, the linker looks for the library path/libname.so. On the target, the runtime linker looks for lib name.so in the library search path.
path
This is an absolute or relative library path used on the host by the linker, and on the target by the runtime linker. A relative path containing a "/" is interpreted as relative to the current directory by the runtime linker. A path without the "/" is searched in the library search path by the runtime linker.
staticLibs: a list of static libraries (.a) that are statically linked.
slDeps: a list of shared libraries on which the resulting library depends. If these libraries are changed, the resulting library slib will be rebuilt. Each library must be defined as a path on the host. Generally slDeps duplicates the libraries described in sharedLibs. To express the dependency without embedding a path in the executable, use the -L path -l name syntax.
options: any linker options, preceded by -Xlinker. This option must be used to supply system-specific linker options which cannot be recognized by the compiler. To pass an option that takes an argument, you must use -Xlinker twice, once for the option and once for the argument.
The following example builds a shared library named libfoo.so from the PIC binary objects files, a.o and b.o. When this library is loaded dynamically, the runtime linker will also load the libshared.so.
SharedLibraryTarget( libfoo.so, a.o b.o, , libshared.so, , )
The following imake macros are used to build shared applications:
SharedUserTarget(prog, shobjs, staticLibs, sharedLibs, slDeps, options) SharedSupTarget(prog, objs, staticLibs, sharedLibs, slDeps, options) SharedCXXUserTarget(prog, objs, staticLibs, sharedLibs, slDeps, options) SharedCXXSupTarget(prog, objs, staticLibs, sharedLibs, slDeps, options)
For more information on each of these macros, refer to "imake Build Rules".
The prog argument is the name of the resulting process. Other arguments are the same as the SharedLibraryTarget() macro. For the options argument, the following options are particularly useful:
-Xlinker -soname=<name>
Within the SharedLibraryTarget() rule, this option sets the internal soname of the library. If a library used as a dependency in a rule that builds a dynamic application has a soname defined, the executable records the soname instead of the sharedLibs argument.
-Xlinker -rpath -Xlinker <dir>
This option defines the runpath directory that is added to the library search path.
The following example builds a shared application named shr_app from the PIC binary object files a.o and b.o. When this process is started, the runtime linker loads the shared libraries libshared.so and libcx.u.so (if required). In the target file system, this library is located in the /libraries directory because this directory will be added to the search path of the runtime linker.
SharedUserTarget( shr_app, a.o b.o, , libshared.so, , -Xlinker -rpath -Xlinker /libraries)
As with shared libraries, it is possible to build shared applications which do not contain .o objects in PIC format. The applications are still able to use shared libraries, however the application code is not shared.