| || |
It is important to note from the outset that the version number of your project is a very different thing to the version number of any libraries shipped with your project. It is a common error for maintainers to try to force their libraries to have the same version number as the current release version of the package as a whole. At best, they will break binary compatibility unnecessarily, so that their users won't gain the benefits of the changes in their latest revision without relinking all applications that use it. At worst, they will allow the runtime linker to load binary incompatible libraries, causing applications to crash.
Far better, the Libtool versioning system will build native shared libraries with the correct native library version numbers. Although different architectures use various numbering schemes, Libtool abstracts these away behind the system described here. The various native library version numbering schemes are designed so that when an executable is started, the runtime loader can, where appropriate, choose a more recent installed library version than the one with which the executable was actually built. This allows you to fix bugs in your library, and having built it with the correct Libtool version number, have those fixes propogate into any executables that were built with the old buggy version. This can only work if the runtime loader can tell whether it can load the new library into the old executable and expect them to work together. The library version numbers give this information to the runtime loader, so it is very important to set them correctly.
The version scheme used by Libtool tracks interfaces , where an interface is the set of exported entry points into the library. All Libtool libraries start with `-version- info ' set to `0:0:0' -- this will be the default version number if you don't explicitly set it on the Libtool link command line. The meaning of these numbers (from left to right) is as follows :
- The number of the current interface exported by the library. A current value of `0' , means that you are calling the interface exported by this library interface 0 .
- The implementation number of the most recent interface exported by this library. In this case, a revision value of `0' means that this is the first implementation of the interface.
If the next release of this library exports the same interface, but has a different implementation (perhaps some bugs have been fixed), the revision number will be higher, but current number will be the same. In that case, when given a choice, the library with the highest revision will always be used by the runtime loader.
- The number of previous additional interfaces supported by this library. If age were `2' , then this library can be linked into executables which were built with a release of this library that exported the current interface number, current , or any of the previous two interfaces.
By definition age must be less than or equal to current . At the outset, only the first ever interface is implemented, so age can only be `0' .
For later releases of a library, the `-version-info' argument needs to be set correctly depending on any interface changes you have made. This is quite straightforward when you understand what the three numbers mean:
- If you have changed any of the sources for this library, the revision number must be incremented. This is a new revision of the current interface .
- If the interface has changed, then current must be incremented, and revision reset to `0' . This is the first revision of a new interface .
- If the new interface is a superset of the previous interface (that is, if the previous interface has not been broken by the changes in this new release), then age must be incremented. This release is backwards compatible with the previous release .
- If the new interface has removed elements with respect to the previous interface, then you have broken backward compatibility and age must be reset to `0' . This release has a new, but backwards incompatible interface .
For example, if the next release of the library included some new commands for an existing socket protocol, you would use
-version-info 1:0:1 . This is the first revision of a new interface. This release is backwards compatible with the previous release .
Later, you implement a faster way of handling part of the algorithm at the core of the library, and release it with
-version-info 1:1:1 . This is a new revision of the current interface .
Unfortunately the speed of your new implementation can only be fully exploited by changing the API to access the structures at a lower level, which breaks compatibility with the previous interface, so you release it as
-version-info 2:0:0 . This release has a new, but backwards incompatible interface .
When deciding which numbers to change in the
-version-info argument for a new release, you must remember that an interface change is not limited to the API of the library. The notion of an interface must include any method by which a user (code or human) can interact with the library: adding new builtin commands to a shell library; the format used in an output file; the handshake protocol required for a client connecting over a socket, and so on.
Additionally, If you use a development model which has both a stable and an unstable tree being developed in parallel, for example, and you don't mind forcing your users to relink all of the applications which use one of your Libtool libraries every time you make a release, then
libtool provides the `-release' flag to encode the project version number in the name of the library, See section 11.2.1 Creating Libtool Libraries with Automake. This can save you library compatibility problems later if you need to, say, make a patch release of an older revision of your library, but the library version number that you should use has already been taken by another earlier release. In this case, you could be fairly certain that library releases from the unstable branch will not be binary compatible with the stable releases, so you could make all the stable releases with `-release 1.0' and begin the first unstable release with `-release 1.1' .