[Xcb] [ANNOUNCE] xcb-util 0.3.9

Josh Triplett josh at joshtriplett.org
Mon Jun 4 23:22:03 PDT 2012

On Mon, Jun 04, 2012 at 04:24:10PM -0700, Jeremy Huddleston wrote:
> On Jun 4, 2012, at 3:25 PM, Josh Triplett <josh at joshtriplett.org> wrote:
> > On Mon, Jun 04, 2012 at 02:52:51PM -0700, Jeremy Huddleston wrote:
> >> On Jun 4, 2012, at 2:19 PM, Adam Jackson <ajax at redhat.com> wrote:
> >>> On Mon, 2012-06-04 at 14:03 -0700, Jeremy Huddleston wrote:
> >>>> On Jun 4, 2012, at 1:34 PM, Julien Cristau <jcristau at debian.org> wrote:
> >>>> Think about this from the libc perspective.  libc *may have* strlcat
> >>>> or not, but they're named the same because all functions in libc have
> >>>> consistent signatures.
> >>> 
> >>> A libc that had strlcat once, and then removed it, would no longer have
> >>> the same ABI.  An application that had successfully linked against the
> >>> old libc's strlcat would reasonably expect it to be present at runtime
> >>> too.
> >> 
> >> That argument breaks down when you reverse it.  The "rules" state that the SONAME should not change when adding APIs.  If all you're basing this on is SONAME, then there is absolutely no difference between the adding and removing case.  If I link against a "newer" libc which has strlcat, then by your argument, I'd expect strlcat to be present on any libc matching that SONAME.  When I run my application with the older libc without strlcat, it will fail to find it.
> > 
> > That represents the difference between major and minor version changes.
> > When you add a new function (or otherwise extend the ABI, such as by
> > adding new flags to a flags parameter), you increase the minor version,
> > so that applications built against the new library won't run with the
> > old one, but applications built against the old one (and thus not
> > expecting the new function) will still work with the new library.
> > However, when you *remove* a function, applications built against the
> > old library will not work with the new one, so you have to bump the
> > major version.
> I guess this is where the "OS X" paradigm and the GNU paradigm just
> break down.  Is there actually annotation done to specify that a
> specific function was added for a given minor version bump of a
> library?  Does the loader just require that the runtime version be >=
> the linktime version (that seems particularly dangerous to me)?  How
> is this actually enforced in practice?  My understanding was that the
> minor version was nothing more than extra bits as a guide to the user
> or packager and that there wasn't actually any "real" mechanism in
> place to deal with this properly (ie weak linking the new symbols).

The dynamic linker has a couple of independent mechanisms to handle
this: the library major/minor version, and symbol versioning.

The major/minor version have a simple rule: a program or library linked
against version $linkmajor.$linkminor of libfoo can run with any libfoo
with $runtimemajor == $linkmajor and $runtimeminor >= $linkminor.  With
ELF on Linux, the minor number requirement just exists as a convention,
not a dynamic linker requirement, though some libraries explicitly
ask the dynamic linker to enforce it using symbol versioning.

The dynamic linker *does* enforce the availability of symbols, though.
If your program or library links against libfoo and expects to find
foo_blah, and a newer libfoo removes foo_blah, the linker will complain
and not load your program or library.

If you want to do something more complicated, you can use symbol
versioning, which lets you say things like "a program expecting the
foo_blah symbol from libfoo.so.1.2 should use old_foo_blah instead; a
program expecting foo_blah from libfoo.so.1.3 should use foo_blah".
glibc does a ton of that, to give it much more fine-grained versioning
so that programs built against one version of glibc will run against the
widest possible selection of glibc versions.  More simple examples
include enforcing the minor version rule, which almost every library
using symbol versioning enforces: programs linking against libfoo.so.1.3
will want various foo_* symbols from libfoo.so.1.3, and only
libfoo.so.1.3 and newer minor versions will have mappings for those
symbols; older minor versions won't have those mappings, so the linker
knows to fail early.

> >> SONAME is not the solution to this problem.  The best practice is to properly annotate "new" functions (so they are weak linked) and not remove public API until it is really warranted.
> >> 
> >> If you're removing a fringe API that is only used internally, then I'd argue against SONAME change.
> > 
> > Only if you know for sure that it won't break any real applications; in
> > other words, does this represent de-facto public API, or not?
> Based on the commit logs, I was under the impression that these
> functions were only meaningful to already-removed functionality.  If
> the removal of that functionality didn't even warrant a version bump,
> why would removing its support APIs?

I don't know the details of the removed functions, and whether they
represent part of a public API or internal implementation details.

- Josh Triplett

More information about the Xcb mailing list