|
11.4 Library Versioning
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:
- current
- 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.
- revision
- 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.
- age
- 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'.
|