Unix Articles |
|||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
HOME ctags Tree Climbing Title Bar |
|||||||||||||||||||||
|
Working with Unix Object LibrariesContentsDisclaimerThis document is unsupported. The information given here is not guaranteed to be useful for any purpose, explicit or implied. It is placed on this web site strictly as a unsupported free service. It is as accurate as the author has been able to verify, and will be updated with additions and corrections as time permits. IntroductionA Unix object library is a group of compiled files combined into a single library file. The standard Unix archiver, ar, is used to combine and maintain these files. The standard naming scheme for these libraries is libXXX.a, where XXX is a brief descriptive string. For example, the system library of math functions is called libm.a. The Athena Widget Library for X Windows is called libXaw.a. By convention, most Unix system libraries are stored in the path /usr/lib. Some libraries may also exist in /lib and in /usr/local/lib, depending on the version of Unix and the system administrator's needs. In contrast, a developer's application-specific libraries may be placed anywhere on the filesystem. The files contained in Unix object libraries have been compiled, but have not yet been linked. These object files usually have the extension ".o" to indicate this state. During the final phase of building an application, the C compiler or system linker is used to link against the object library. This makes building an application with an object library considerably faster than compiling the separate routines down from source. Object libraries are useful for other reasons as well. They provide a mechanism for combining multiple related functions. Libraries simplify code re-use, providing ready access to debugged routines. A standard header file is usually provided for each object library to provide prototypes for library functions. This allows the compiler to verify correct function parameter types for each library call. Note the distinction between a Unix "object file" and the concept of an object under object-oriented programming; there is no connection between the two. The term "object" has been used to refer to unlinked compiled code under Unix since long before OOP became widely known. Unix object files are created using the "-c" parameter of the standard C compiler, cc, and the HP C++ compiler, CC, as well. C++ Class LibrariesWhen C++ Class Libraries are built for Unix systems, object libraries are how they are stored. Our HP-UX standard C++ class library is stored as /usr/lib/libC.a. This library contains object modules that contain the iostream and fstream classes, among others. This library is linked to a C++ program by default, much as /lib/libc.a (the standard C library) is linked to an ANSI C program whenever one is compiled. Header files for the HP-UX C++ class libraries are stored in /usr/include/CC. For example, the iostream class library header is /usr/include/CC/iostream.h. This path is searched automatically when the header file is included between "<" and ">" brackets in the #include precompiler statement; therefore
#include <iostream.h>
is all that's required for the compiler to find the header file. Header files for application-specific C++ class libraries may be placed anywhere on the filesystem; if this is done, the "-I" parameter will be needed to specify the path to the include files. Note that while header files are not directly related to the concept of a Unix object library, in practice, it is difficult to discuss one without referring to the other. Header files are essential in that they provide the information necessary to interface with an object library. How to Create an Object LibraryAs stated above, ar, the standard Unix archiver, is routinely used to create Unix object libraries. The resulting file, which ends in ".a", can therefore be referred to as an archive; however, the term library is recommended as it is more descriptive for our purposes. Archive files created by ar can contain any type of file, including text and executable files; in contrast, object libraries contain only compiled object files. The syntax for building a library from a group of object files is
ar r <library file> <list of object files>
for example,
ar r libmultidim.a hypercube.o mobius_strip.o klien_bottle.o tesseract.o
will create a library in the current directory called libmultidim.a, which contains the four object files given in the example. Note: some versions of Unix require an additional step to prepare an object library, which is building a symbol table. This operation requires the ranlib utility. Under some Unixes, including HP-UX, ar builds the symbol table automatically. The Unix make utility has built-in rules that allow convenient building and maintaining of object libraries. ar can update an individual object file "on the fly", without having to rebuild the entire library. For this reason, updating an object library is usually as simple as editing a particular source file and typing "make". The rest is done automatically, with the help of an appropriately written Makefile. Finding Out What's Inside an Object Libraryar has several options, and one of them, the "t" parameter, tells it
to print a table of contents for the archive. For our example, typing
hypercube.o mobius_strip.o klien_bottle.o tesseract.o It is possible to list the symbols used by the files inside our library using the Unix nm (for "name symbols") command. When one types
nm libXXX.a
each object file within the library is shown, followed by a list of the symbols within the object file. nm may also be used to examine the symbol tables of individual object files and executable programs. Keep in mind that for this to work, the "-g" parameter of the compiler must be used to include the symbolic information. In addition, if strip is used to remove the symbol table from an executable program, nm will no longer be able to list it's contents. Updating an Object LibraryWhat do we do if we need to change just one of the object files within a library? ar makes this straightforward. The same parameter used to build the library, "r", also has the function of replacing an object file in an archive with a new version.
ar r libmultidim.a hypercube.o
would remove the existing object file hypercube.o from the library, and insert an object file with the same name from the current working directory. At the same time, the library's symbol table is rebuilt to reflect any changes. Removing and Extracting Object Files from a LibraryOccasionally it is useful to remove an object file from a library. This is necessary when one of the internal files' functions are replaced by those in another file, or when an object file must be renamed. ar performs this operation using the "d" parameter. Typing
ar d libmultidim.a hypercube.o
would delete the hypercube.o object file from the library. It is unlikely that we will have need to extract an object file from a library, but for completeness' sake, the "x" parameter provides this ability. Typing
ar x libmultidim.a hypercube.o
will extract a copy of hypercube.o into the current directory. Note that the object file will continue to exist inside the library. Also note that if a file already existed with the same name in the current directory, it could be silently overwritten -- unless the user's shell is set to warn of this condition. Linking An Object Library to an ApplicationThe parameters and syntax that are used to link Unix object libraries to applications have become standardized. "-l" is used to specify each individual object library. "-L" is used to specify the pathnames on which to search for object libraries. Library names are normally abbreviated, when specified to the compiler, using the "-l" parameter. This differs from how source and object file names are provided. Since object library names have the format "libXXX.a", the beginning "lib" and the final ".a" are stripped from the library name in the parameter specification. For example, to link the standard math library /lib/libm.a to your program, you need only specify "-lm" in the compile/link command. The compiler uses this information to build the library name, and links it in. Using our example library libmultidim.a, we would convert this to "-lmultidim" in the compile/link command (note that these commands will most likely be made part of an automated build process). As mentioned previously, the paths to standard system libraries are built into the compiler and do not need to be explicitly stated. Application-specific library pathnames, however, need to be specified using the "-L" parameter, one for each pathname. The path for each application-specific library must be placed prior to the "-l" parameter specifying the library itself. The library path specification need only be given once; the linker will thereafter search the specified path for each subsequent library in the compile/link command. A complete specification for an example application compile & link, using the Unix math library and our example object library, would be
For the sake of completeness, it's necessary to mention that this clever arrangement for linked library specification can be ignored, if one uses the entire path and library filename in the "-l" specification. If a single library in a nonstandard location is needed, it can be specified using, for example,
If there are several libraries to include, this method can make builds difficult to write. Unix ANSI C Object Library & Header OrganizationStandard Unix libraries, such as the math library libm.a, require one or more standard header files (in /usr/include) along with the object files in the library itself. The header files for ANSI C libraries contain, in general, three categories of items that will need to be public, or visible to user programs. These items are
These elements provide the interface for correctly accessing the object libraries' functions. Precompiler macros, for instance, replace library functions for some simple, frequently used routines; getc() and putc() are two examples. Common structures provide consistent means of handling data formats that are standard to the Unix operating system. For example, struct tm in time.h is a complete means of referencing time under Unix. Function prototypes are an important way to ensure that library functions are being correctly referenced, under ANSI C. The ability of modern compilers to flag errors in function parameters saves an enormous amount of time spent debugging. Header files must be well documented to be useful. Standard Unix libraries are documented in the man pages under category #3, User Library Functions. For individual application libraries, the method of documentation usually is comprised of the library specification, combined with consistent and adequate comments in the header files themselves. The object library code for Unix standard libraries is usually proprietary, and is unavailable to the application developer. This code is considered private in scope, and contains the body code for the functions described in the header file(s) for the library. Since standardized means of accessing the library functions are provided and well documented, there is no need to reference the internal code in these libraries. Unix C++ Class Library & Header OrganizationUnix C++ class library header files contain, primarily, C++ class definitions. These class definitions have various public definitions needed by applications developers. Some of these elements are
With the exception of small inline member function definitions, the majority of the member functions are defined in the separately compiled object library code. Since the standard C++ header files use full OOP data hiding, there is no question of access to class library internal variables. Use of the well-defined standard class library interfaces is therefore required. Many C++ class library functions use the ANSI C library functions internally. Since C++ is "downwardly compatible" with ANSI C, it makes sense to use the predefined and well-tested functions in the standard libraries, when the need arises. For this reason several of the C++ class library headers include, within themselves, ANSI C standard Unix library headers. Shared LibrariesShared libraries take the concept of Unix object libraries a step further in making their functions generally available. They allow a commonly-used library to be linked such that it can be loaded into memory, and made available to other programs without having to have its compiled object code combined with the executable program. Referencing shared libraries makes an application smaller, since the library's object files are not a part of the executable program. A reference table is placed in the executable instead, which the system dynamic loader, dld.sl, can use to find the shared library functions. Since the shared library is already memory resident, the application loads and runs faster. Building shared libraries requires system-specific tools, and is not very portable between different Unix platforms. For this reason, using them for non-system level applications is a serious undertaking. The process of building and maintaining shared libraries is more complex, but for frequently used, system-wide applications, the overhead is worth the trouble. This topic may be expanded in future revisions of this document. ReferencesThe best source of information regarding Unix object libraries is, fortunately or not, the man pages on your system. "man ar", for example, will provide a list of many more options for building and maintaining object libraries than are provided here. Other man pages of interest include:
Working with Unix Object Libraries is Copyright © 1997 by Scott Chilcote. | ||||||||||||||||||||