[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Proposal: An OOC Package Tool



Christian Stork <cstork@ics.uci.edu> writes:

> Michael van Acken <acken@vanacken.do.uunet.de> wrote:
> >The interface of a package is versioned, e.g. using the libtool
> >numbering scheme.  Versioning is based on the binary interface of the
> 
> Could you shortly explain this numbering scheme if it goes beyond simple
> numbers for different interfaces?

Here is an excerpt of the libtool info pages.  It also explains the
motivation behind this particular numbering scheme.

-- mva


File: libtool.info,  Node: Versioning,  Next: Library tips,  Prev: Integrating libtool,  Up: Top

Library interface versions
**************************

   The most difficult issue introduced by shared libraries is that of
creating and resolving runtime dependencies.  Dependencies on programs
and libraries are often described in terms of a single name, such as
`sed'.  So, I may say "libtool depends on sed," and that is good enough
for most purposes.

   However, when an interface changes regularly, we need to be more
specific: "Gnus 5.1 requires Emacs 19.28 or above."  Here, the
description of an interface consists of a name, and a "version number."

   Even that sort of description is not accurate enough for some
purposes.  What if Emacs 20 changes enough to break Gnus 5.1?

   The same problem exists in shared libraries: we require a formal
version system to describe the sorts of dependencies that programs have
on shared libraries, so that the dynamic linker can guarantee that
programs are linked only against libraries that provide the interface
they require.

* Menu:

* Interfaces::                  What are library interfaces?
* Libtool versioning::          Libtool's versioning system.
* Updating version info::       Changing version information before releases.
* Release numbers::             Breaking binary compatibility for aesthetics.



File: libtool.info,  Node: Interfaces,  Next: Libtool versioning,  Up: Versioning

What are library interfaces?
============================

   Interfaces for libraries may be any of the following (and more):

   * global variables: both names and types

   * global functions: argument types and number, return types, and
     function names

   * standard input, standard output, standard error, and file formats

   * sockets, pipes, and other inter-process communication protocol
     formats

   Note that static functions do not count as interfaces, because they
are not directly available to the user of the library.


File: libtool.info,  Node: Libtool versioning,  Next: Updating version info,  Prev: Interfaces,  Up: Versioning

Libtool's versioning system
===========================

   Libtool has its own formal versioning system.  It is not as flexible
as some, but it is definitely the simplest of the more powerful
versioning systems.

   Think of a library as exporting several sets of interfaces,
arbitrarily represented by integers.  When a program is linked against
a library, it may use any subset of those interfaces.

   Libtool's description of the interfaces that a program uses is
simple: it encodes the least and the greatest interface numbers in the
resulting binary (FIRST-INTERFACE, LAST-INTERFACE).

   The dynamic linker is guaranteed that if a library supports *every*
interface number between FIRST-INTERFACE and LAST-INTERFACE, then the
program can be relinked against that library.

   Note that this can cause problems because libtool's compatibility
requirements are actually stricter than is necessary.

   Say `libhello' supports interfaces 5, 16, 17, 18, and 19, and that
libtool is used to link `test' against `libhello'.

   Libtool encodes the numbers 5 and 19 in `test', and the dynamic
linker will only link `test' against libraries that support *every*
interface between 5 and 19.  So, the dynamic linker refuses to link
`test' against `libhello'!

   In order to eliminate this problem, libtool only allows libraries to
declare consecutive interface numbers.  So, `libhello' can declare at
most that it supports interfaces 16 through 19.  Then, the dynamic
linker will link `test' against `libhello'.

   So, libtool library versions are described by three integers:

CURRENT
     The most recent interface number that this library implements.

REVISION
     The implementation number of the CURRENT interface.

AGE
     The difference between the newest and oldest interfaces that this
     library implements.  In other words, the library implements all the
     interface numbers in the range from number `CURRENT - AGE' to
     `CURRENT'.

   If two libraries have identical CURRENT and AGE numbers, then the
dynamic linker chooses the library with the greater REVISION number.



File: libtool.info,  Node: Updating version info,  Next: Release numbers,  Prev: Libtool versioning,  Up: Versioning

Updating library version information
====================================

   If you want to use libtool's versioning system, then you must specify
the version information to libtool using the `-version-info' flag
during link mode (*note Link mode::.).

   This flag accepts an argument of the form
`CURRENT[:REVISION[:AGE]]'.  So, passing `-version-info 3:12:1' sets
CURRENT to 3, REVISION to 12, and AGE to 1.

   If either REVISION or AGE are omitted, they default to 0.  Also note
that AGE must be less than or equal to the CURRENT interface number.

   Here are a set of rules to help you update your library version
information:

  1. Start with version information of `0:0:0' for each libtool library.

  2. Update the version information only immediately before a public
     release of your software.  More frequent updates are unnecessary,
     and only guarantee that the current interface number gets larger
     faster.

  3. If the library source code has changed at all since the last
     update, then increment REVISION (`C:R:A' becomes `C:R+1:A').

  4. If any interfaces have been added, removed, or changed since the
     last update, increment CURRENT, and set REVISION to 0.

  5. If any interfaces have been added since the last public release,
     then increment AGE.

  6. If any interfaces have been removed since the last public release,
     then set AGE to 0.

   **Never** try to set the interface numbers so that they correspond
to the release number of your package.  This is an abuse that only
fosters misunderstanding of the purpose of library versions.  Instead,
use the `-release' flag (*note Release numbers::.), but be warned that
every release of your package will not be binary compatibility with any
other release.