Package and Library Versioning
- From: Tim Janik <timj gnu org>
- To: rapicorn googlegroups com
- Cc: beast gnome org
- Subject: Package and Library Versioning
- Date: Sun, 18 Oct 2015 21:42:55 +0200
This is a summary about a recent discussion Stefan and I had about aidacc, libbse and librapicorn versioning,
comments and corrections are welcome.
Note, an SONAME is the shared-object (library) name, encoded in an ELF library that
determines a library ABI. If the SONAME changes, the ABI changes. Example:
objdump -p librapicorn-15.09.so.1.0.1 | fgrep SONAME
SONAME librapicorn-15.09.so.1
# Current versioning State
* Rapicorn encodes the year of a release as MAJOR and the month as MINOR, MICRO is incremented for
development versions (odd) and releases (even).
* With the recent packaging overhaul (#219d818bce8741abb4befc3520ed823a016c1934), there can be parallel
installations of rapicorn that have different MAJOR or MINOR versions.
* The SONAME depends on MAJOR.MINOR and MICRO, changing MAJOR or MINOR *forces* ABI breaks; through ABI
aging, changing MICRO may break or retain ABI (details here:
https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html, we use LT_CURRENT=MICRO).
* Configure supports --enable-devel-mode which enables additional build rules (details below), this currently
autosenses odd MICRO versions.
* Note that during development ABI may be broken, in such cases the binary age is reset and library linking
is handled correctly (important for developers and users that try snapshot packages).
* Python modules include MAJOR.MINOR under the hood, e.g. besides "import Rapicorn" this also works: "import
Rapicorn_15_09 as Rapicorn"
* Rapicorn redefines the C++ namespace to the current MAJOR.MINOR version, e.g. "rapicornconfig.h:#define
Rapicorn Rapicorn_15_09". This can in theory allow linking different rapicorn library versions into the same
program.
* The continuous integration scripts that build snapshot packages are using MAJOR.MINOR.MICRO-tCOMMITTOTAL,
e.g. "15.09.1-t4984", where COMMITTOTAL is monotonically increasing and can be retrieved via `git rev-list
--count HEAD` in a complete repository, so commits can be related to snapshots.
# Versioning considerations for the future
* It can be desirable to reflect the _year_ of a release in a version number, case:
http://blog.codinghorror.com/whats-in-a-version-number-anyway/
* We may need to allow parallel installations of different MAJOR versions, in case porting between versions
takes considerable time. But parallel installations of different MINOR versions is probably overkill.
* For parallel installation, debian packages would be named similar to:
rapicorn-15_15.09.1-t5011-1_amd64'.deb, i.e. NAME='rapicorn-15', UPSTREAM_VERSION='15.09.1',
SNAPSHOT_VERSION='t5011' if applicable, DEBIAN_PKGVERSION='1', ARCH='amd64'. See also:
https://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Version
* To support longer ABI stability periods in the future, we can use LT_CURRENT=MINOR and decouple MINOR from
the release months. That will allow MINOR version changes to break or _retain_ ABI. But that way MICRO
version changes will never break ABI.
* Note that ABI breakage during development will then require *MINOR* version bumps. That in turn requires a
MICRO version reset to zero. So now development versions cannot be easily detected via odd MICROs. That in
turn means --enable-devel-mode requires different autosensing logic.
* Possible solution: let configure default to --enable-devel-mode=no, but pass --enable-devel-mode=yes
through autogen.sh (which can be overridden via ./autogen.sh --enable-devel-mode=no), so ./configure in
tarballs has devel-mode disabled, while normal git repository builds where autogen.sh is used will have it
enabled.
* Retain Python module versioning for MAJOR version, i.e. support "import Rapicorn" for the latest version
and: "import Rapicorn_15 as Rapicorn"
* Give up on the C++ namespace versioned renaming, there's no foreseeable use case for linking against
multiple Rapicorn versions at the same time and some of the dependencies or included code portions like rsvg
may cause additional problems in such a scenario. C++ library version selection generally happens through
pkg-config.
* The .pc file becomes: pkg-config rapicorn-15 --print-provides; # rapicorn-15 = 15.09.1
* If lengthy periods of ABI stability are required in the future, we can always switch to keep the MAJOR
version number stable across multiple years and if it's worth the effort use symbol versioning (glibc does
this).
# Devel-Mode
This mode is currently enabled for odd MICRO versions, releases currently use even MICRO revisions.
Enabling this mode does the following:
* define -D__FILE_DIR__=\"${abs_srcdir}\" so assert() and friends can produce source locations that are
easier to debug
* more sources and documentation files are rebuild, which introduces additoinal dependencies: bison, flex,
doxygen, dot, pandoc, xmllint
* devel-mode requires the .git repository, e.g. for ChangeLog generation
* documentation uploads go to <stable> or 'latest' depending on devel-mode
* additional debugging code can be enabled at runtime by checking Rapicorn::debug_devel_check()
# Related
Just as food for further thoughts on versioning:
- ELF symbol versioning example: https://www.berrange.com/posts/2011/01/13/versioning-in-the-libvirt-library/
- Why to encode the MAJOR version as SONAME and not via `libtool -release`:
https://autotools.io/libtool/version.html
- Debian New Maintainers' Guide - A.1. Shared libraries:
https://www.debian.org/doc/manuals/maint-guide/advanced.html#library
- Naming shared library packages (deb):
https://www.netfort.gr.jp/~dancer/column/libpkg-guide/libpkg-guide.html#naminglibpkg
- C++11 comes with inline namespaces to support symbol versioning at the C++ level:
http://stackoverflow.com/questions/11016220/what-are-inline-namespaces-for/11018418#11018418
--
Yours sincerely,
Tim Janik
https://testbit.eu/timj/
Free software author and speaker.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]