| United States-English |
|
|
|
![]() |
HP-UX Linker and Libraries User's Guide: HP 9000 Computers > Chapter 5 Creating and Using Libraries Version Control with Shared Libraries |
|
HP-UX provides two ways to support incompatible versions of shared library routines. “Library-Level Versioning ” describes how you create multiple versions of a shared library. “Intra-Library Versioning ” describes how a single shared library can have multiple versions of an object module. Library-level versioning is recommended over intra-library versioning.
For the most part, updates to a shared library should be completely upward-compatible; that is, updating a shared library won't usually cause problems for programs that use the library. But sometimes — for example, if you add a new parameter to a routine — updates cause undesirable side-effects in programs that call the old version of the routine. In such cases, it is desirable to retain the old version as well as the new. This way, old programs will continue to run and new programs can use the new version of the routine. Here are some guidelines to keep in mind when making changes to a library:
When using shared library versioning, you need to save the old versions of modules in the library:
HP-UX 10.0 adds a new library-level versioning scheme that allows you to maintain multiple versions of shared libraries when you make incompatible changes to the library. By maintaining multiple versions, applications linked with the older versions continue to run with the older libraries, while new applications link and run with the newest version of the library. Library-level versioning is very similar to the library versioning on UNIX System V Release 4. To use library-level versioning, follow these steps:
When you create a new version of the library with incompatible changes, repeat the above steps except increment the number in the suffix of the shared library file name. That is, create libA.1 rather than libA.0 and set the symbolic link libA.sl to point to libA.1. Applications linked with libA.0 continue to run with that library while new applications link and run with libA.1. Continue to increment the suffix number for subsequent incompatible versions, for example libA.2, libA.3, and so forth. If you have an existing library you can start using library-level versioning. First rename the existing library to have the extension .0. Then create the new version of the library with the extension .1 and an internal name using the .1 extension. Create a symbolic link with the extension .sl to point to the .1 library. When you run a program that uses shared libraries and was linked before HP-UX 10.0, the dynamic loader first attempts to open the shared library ending in .0. If it cannot find that library, it attempts to open the library ending in .sl. The +h option gives a library an internal name for library-level versioning. Use +h to create versioned libraries:
internal_name is typically the same name as the library file itself, for example libA.1 as in +h libA.1. When you link with a library that has an internal name, the linker puts the internal_name in the shared library dependency list of the executable or shared library being created. When running the resulting executable or shared library, it is the library named by this internal name that the dynamic loader loads. You can include a relative or absolute path with the internal name, but you must ensure the dynamic loader can find the library from this name using its normal search process. For 32-bit mode, if internal_name includes a relative path (that is, a path not starting with /), the internal name stored by the linker is the concatenation of the actual path where the library was found and internal_name, including the relative path. When the resulting program is run, if the dynamic loader cannot find the library at this location, the program will not run. If internal_name includes an absolute path (that is, a path starting with /), the internal name stored by the linker is simply the internal_name, including the absolute path. When the resulting program is run, if the dynamic loader cannot find the library at this location, the program will not run. For 64-bit mode, see “Internal Name Processing” for more information. This section discusses the situation where you have used the ln(1) command to create file system links to shared library files. For example:
During a link, the linker records the file name of the opened library in the shared library list of the output file. However, if the shared library is a file system link to the actual library, the linker does not record the name of the library the file system link points to. Rather it records the name of the file system link. For example, if /tmp/libmine.sl is a file system link to /X/libapp.sl, the following command records /tmp/libmine.sl in a.out, not /X/libapp.sl as might be expected:
To use library-level versioning in this situation, you must set up corresponding file system links to make sure older applications linked with the older libraries run with these libraries. Otherwise, older applications could end up running with newer shared libraries. In addition, you must include the absolute path name in the internal name of the new library. For example, in 32-bit mode, to make the above example work correctly with library-level versioning, first implement library-level versioning with the actual library /X/libapp.sl and include the absolute path in the internal name of the new library:
Then set up the corresponding file system links:
With these links in place, the loader will load /X/libapp.0 when running the a.out file created above. New applications will link and run with /X/libapp.1.
For 64-bit mode programs, the dynamic loader only loads the library recorded in the dynamic load table. You should use library-lever versioning and create your 64-bit shared library with an internal name unless the library will not be versioned in the future. Once library level versioning is used, calls to shl_load(3X) should specify the actual version of the library to be loaded. For example, if libA.sl is now a symbolic link to libA.1, then calls to dynamically load this library should specify the latest version available when the application is compiled as shown below:
This insures that when the application is migrated to a system that has a later version of libA available, the actual version desired is the one that is dynamically loaded. Intra-library versioning is a second method of maintaining multiple incompatible versions of shared library routines. Library-level versioning is recommended over intra-library versioning. This section provides information on the following topics: With intra-library versioning, you assign a version number to any module in a shared library. The version number applies to all global symbols defined in the module's source file. The version number is a date, specified with a compiler directive in the source file. The syntax of the version number directive depends on the language:
The date argument in all three directives is of the form month/year. The month must be 1 through 12, corresponding to January through December. The year can be specified as either the last two digits of the year (94 for 1994) or a full year specification (1994). Two-digit year codes from 00 through 40 represent the years 2000 through 2040. This directive should only be used if incompatible changes are made to a source file. If a version number directive is not present in a source file, the version number of all symbols defined in the object module defaults to 1/90. A shared library as a whole can be thought of as having a version number itself. This version number is the most recent of the versioned symbols in the library and any dependent libraries. When a shared library is built with a dependent shared library, the version number of the dependent library used during the link is recorded with the dependency. When shl_load(3X) is called to load a shared library, the latest version of the library is loaded. If that library has dependencies, the dynamic loader (dld.sl(5)) will load the versions of the dependent libraries that were recorded in the dependency list. Note that these are not necessarily the most recent versions of the dependent libraries. When dld.sl loads a particular version of a shared library, it will load the same version of any dependent libraries. If a shared library lists a second shared library as a dependency, dld.sl will generate an error if the second shared library has a version number which is older than the version number recorded with the dependency. This means that the first library was built using a more recent version of the second library than the version that dld.sl currently finds. To rebuild a shared library with new versions of object files, run ld again with the newly compiled object files. For example, suppose you want to add new functionality to the routines in length.c, making them incompatible with existing programs that call libunits.sl. Before making the changes, make a copy of the existing length.c and name it oldlength.c. Then change the routines in length.c with the version directive specifying the current month and date. The following shows the new length.c file:
To update libunits.sl to include the new length.c routines, copy the old version of length.o to oldlength.o; then compile length.c and rebuild the library with the new length.o and oldlength.o:
Thereafter, any programs linked with libunits.sl use the new versions of length-conversion routines defined in length.o. Programs linked with the old version of the library still use those routines from oldlength.o. For details on linking with shared libraries, see Chapter 3 “Linker Tasks”. When adding modules to a library for a particular release of the library, it is best to give all modules the same version date. For example, if you complete file1.o on 04/93, file2.o on 05/93, and file3.o on 07/93, it would be best to give all the modules the same version date, say 07/93. The reason for doing this is best illustrated with an example. Suppose in the previous example you gave each module a version date corresponding to the date it was completed: 04/93 for file1.o, 05/93 for file2.o, and 07/93 for file3.o. You then build the final library on 07/93 and link an application a.out with the library. Now suppose that you introduce an incompatible change to function foo found in file1.o, set the version date to 05/93, and rebuild the library. If you run a.out with the new version of the library, a.out will get the new, incompatible version of foo because its version date is still earlier than the date the application was linked with the original library! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||