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.

_______________________________________________
beast mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/beast

Reply via email to