Libraries in CMT and Gaudi |
Purpose
This page is an attempt to explain some of the basic concepts about libraries, libraries in CMT and Gaudi libraries in CMT.
Note: [ ... ] denote comments concerning simple things (like suffixes) that are system-dependant.
Libraries in General (I'm talking about C++ libraries here, though I shan't keep writing that, cuz I'm lazy)
Conceptually, a library is a collection of object modules kept in a single file with some kind of directory structure so that the individual any particular module can be found. This is a convenience when linking: it is not necessary to enumerate the individual object modules needed to resolve references when linking; it suffices to include the library as input to the linker and the linker will find the modules it needs.
There are two kinds of library: static and shareable. When supplied as input to the linker, they are treated differently. When a static library is input to the linker, the procedure is roughly the following:
- The linker searches the directory to see which heretofore unresolved references in the entity it is linking can be resolved by objects in the library.
- These modules are copied to the output; references to them are adjusted accordingly
For a shareable library, however, there is an extra level of indirection. It could be something like this (I don't claim to describe any real linker, but this should be close to the behavior of the old DEC VMS linker)
- The linker searches the directory to see which heretofore unresolved references in the entity it is linking can be resolved by objects in the library (same as for static).
- The linker makes a sort of copy of the directory, which consists of a set of pairs
but leaves a "blank" for the offset field.
module name offset from start of shareable - The linker partially resolves a reference to an object in the shareable by inserting the address of the blank location field in the (copied) directory entry.
Unlike the static library case, there is more to be done and this is perhaps the most important difference between shareable and static libraries: the loader has to finish the job of resolving references at run time. An invented loader to go with the invented linker above could "fix up" the blank directory entries by first finding the shareable at runtime and loading it into memory, keeping track of the address where it was loaded, then fill in the blank with a jump instruction whose target is the start of the shareable plus the offset for that object. The offset is read from the directory of the shareable loaded, not necessarily the same as the one that was linked against (though with this scheme there are some constraints on the directoriesof the link-time and run-time shareables)
Another difference between the two libraries is the information needed at link time. In the shareable case, the object modules themselves are not needed; only the directory.
Finally the system must know where to look for shareable libraries that might be linked into your executable. This is done via environment variables, PATH for Windows and LD_LIBRARY_PATH for unix.
Libraries in CMT
The CMT philosophy is to divide code into packages, which contain classes that have some similar purpose. It is therefore natural that one would compile these classes and link them into a library. To create a library one uses the following command in the requirements file for the package
library Particles proton.cxx electron.cxx muon.cxx
The above command creates a shareable library called Particles.dll [ libParticles.so on unix]. If you wish to create a static library use the -no_share flag
library Particles -no_share proton.cxx electron.cxx muon.cxx
CMT understands how to build the library based on the above command. But one also needs to specify how to link using this library. For instance suppose we had another package, called Physics, that depended on the static version of the Particles library. Assume the library Particles is in a package which is also called Particles. In that case we would need to specify the linking options for the Particles package as follows
macro Particles_linkopts " ${PARTICLESROOT}/${DEBUGDIR}/libParticles.lib "
CMT by default looks for a macro of the form <package>_linkopts in order to define the linking option for this package. So in this case CMT knows that linking option for Particles is to simply include the static Particles library (Note: PARTICLESROOT is a predefined CMT macro which points to the base of the package, DEBUGDIR is the directory under the base where the binaries are installed).
Remember, however, that we use CMT to deal with the differences from platform to platform. Therefore we should actually use a version of the above command that can deal with either unix or Windows environment.
macro Particles_linkopts " ${PARTICLESROOT}/${DEBUGDIR}/libParticles.a "
VisualC " ${PARTICLESROOT}/${DEBUGDIR}/libParticles.lib "The above command says that Particles_linkopts defaults to the unix version of the library, but uses the Windows version if we are on Windows (which is specified by the VisualC tag).
Libraries in Gaudi
Libraries in Gaudi add an additional level of complexity. Gaudi distingusihes two types of libraries: linker libraries and component libraries. These libraries are built and used in different fashions.
1) Linker Libraries - These are both static and shareable libraries that are used to link executables as described in the sections above. Linker libraries export all their symbols and are needed during the link phase. So if package A depends on package B, package A needs the package B library (be it a shareable or a static library) during the linking phase.
2) Component libraries - "[Component] libraries contain one or many software components implementing a number of abstract interfaces" - this description is right out of the Gaudi manual. Component libraries have the following features
- They are shareable libraries
- Access to the components in a component library is done through the component's abstract interfaces.
- These interfaces are designed in such a way that an executable using a component does not need to link against the component during the build process. Rather the component is loaded at run-time by the Gaudi framework, which then resolves the symbols in the component library. Again from the Gaudi manual "These [component] libraries do not export symbols (they export only one which is used by the framework to dixcover what the library contains)".
Writing a component library necesitates the following in-code features
- There are a couple specific definitions that Gaudi needs in order to be able to load the component library at run-time. These definitions are in files called <component>_dll.cpp and <component>_load.cpp, that are generally in the directory src/Dll/. There are numerous examples of these files in the Glast and Gaudi packages.
- When components are used, they must be accessed through their abstract interfaces in such a way that the component library is not needed during the link phase.
A component also needs some specific definitions in the requirements file for the package it is in
library ReconComp Recon/*.cpp Dll/*.cpp
set ReconCompShr "${RECONCOMPROOT}/${DEBUGDIR}/libReconComp"
private
macro ReconComp_shlibflags
"$(componentshr_linkopts) $(use_linkopts)" \
VisualC
"$(componentshr_linkopts) $(use_linkopts) $(Win32Debug)"
Couple comments:
Finally one needs to explicitly load the component at run-time. This can be done, for instance, in the jobOptions.txt file, by specifying
ApplicationMgr.DLLs += { "ReconComp" };
A note on terminology: Gaudi chose to use the term "dll" in much of it s in-code reference to component libraries. For instance, in the above command one makes reference to ApplicationMgr.DLLs
This is a somewhat confusing convention for two reason
When describing Gaudi libraries, make sure to keep these subtleties in mind.
T. Lindner Last Modified: 2002-03-20 14:33:53 -0800