bug-readline
[Top][All Lists]
Advanced

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

Re: [Bug-readline] Set correct -compatibility_version in .dylib on Mac O


From: Max Horn
Subject: Re: [Bug-readline] Set correct -compatibility_version in .dylib on Mac OS X
Date: Wed, 5 Oct 2016 20:41:45 +0200

Hi there,

so I am reviving this old thread, where a patch of mine was not added. My 
mistake for not noticing, and not clarifying. To summarize what I suggested 
back then, and am still suggesting for readline 7:

The handling of compatibility_version on Darwin / Mac OS X is incorrect. 
Instead of this

  -compatibility_version $(SHLIB_MAJOR)

it should use this:

  -compatibility_version $(SHLIB_MAJOR)$(SHLIB_MINOR)

The long version follows.

> On 28 Apr 2014, at 00:50, Chet Ramey <address@hidden> wrote:
> 
> Signed PGP part
> On 4/25/14, 2:51 PM, Max Horn wrote:
> 
> > That is incorrect (and I tried to explain in my email why that is).
> >
> > First off, the change is necessary because new API was added -- it would 
> > have been necessary for 6.2, 6.1, etc., too, just nobody noticed.
> 
> OK.  I'm under the impression that Mac OS X treats compatibility_version
> like DT_SONAME.

This is incorrect.

> 
> For those not familiar, Unix systems that use ELF shared libraries set
> them up
> 
> libabsinthe.so -> libabsinthe.so.6
> libabsinthe.so.6 -> libabsinthe.so.6.5
> 
> where libabsinthe.so.6.5 is a real file, in this case the newest version.
> The soname in this example is libabsinthe.so.6.  libabsinthe.so.6.5 sets
> the DT_SONAME field to libabsinthe.so.6 (the soname).

OS X also does that. The compatibility_version and current_version are 
additional features.

For an "official" explanation, see e.g. here 
<https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html#//apple_ref/doc/uid/TP40002013-SW20>/

Though that article contains some obvious errors in the "Defining Client 
Compatibility"... Another point of reference, if one is so inclined, is to read 
the source of Apple's dyld (which I did, and did again to prepare this email).

In the article, they refer to the "major", "minor" and "compatibility" versions 
of a dylib.

The "major" version corresponds roughly to DT_SONAME, and is also known as 
"install_name" on OS X (see also the linker option -install_name). It needs to 
be changed for breaking ABI changes, such as removal of APIS. Some examples:

  libreadline.6.dylib -> indicates major version 6
  libreadline.7.dylib -> indicates major version 7
  libSystem.A.dylib   -> indicates major version A (Apple likes to use letters 
for these)

They denote binary incompatible versions, and usually you increment them, 
though you don'th ave to (you are free to go from A to 7 to D to 5, if you 
think that's a good idea...). Anyway, readline of course gets this right.



Next is what Apple calls the "minor" version, corresponding to the 
"-current_version" switch of Apple libtool (not to be confused with GNU 
libtool, a totally different thing). The current_version is completely 
independent of the major version / SONAME. You typically increment this with 
each new release of your library. In any case, you *must* increment it when you 
add new ABIs (more on that later). For example, this is the OS X 10.11 system 
library on my machine:

  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 
1226.10.1)

As you can see, the major version is "B", and has nothing to do with the 
current version, nor the compatibility version.
So, while readline currently sets this to $(SHLIB_MAJOR)$(SHLIB_MINOR), that is 
actually unnecessary -- you could just as well set it to $(SHLIB_MINOR) with no 
loss in meaning -- though once one chooses a scheme, one needs to stick to it 
(i.e. only change the scheme when the major version / SONAME changes).
Anyway, the way readline does this currently is just fine, the extra redundant 
SHLIB_MAJOR does not cause any problems.



Finally, there is the compatibility version, set via the 
"-compatibility_version" switch. Very roughly, this must be less or equal than 
the "minor / current" version. You *must* increase it if new APIs are added. 
Typically, you'll then set it to the minor / current version of the library at 
the time the feature was added (though strictly speaking, that's not actually 
necessary; but let's not complicate things even more ;-).

A good way of thinking about current_version and compatibility_version is as of 
a min/max range (indeed, that's how dyld refers to them in its source code). 
There value in a dylib roughly conveys the message "I am compatible with every 
binary which was linked against a version of me which is at least as high as my 
compatibility_version".

Currently, readline sets this to $(SHLIB_MAJOR) -- which, for readline 7, is 
equivalent to setting it to 7.0.0.

If readline 7.1 were to only fix bugs, that would be fine. But in the past, 
such things were handled by patches. So, it is quite likely that readline 7.1 
will add some new APIs. If you do not change the shobj-conf, then that version 
of libreadline.7.dylib will also have compatibility version 7.0.0, and "current 
version" 7.1.0.

The result: The dynamic linker dyld would assume that any executable linked 
against 7.1.0 also works fine with 7.0.0. But of course this is wrong (in this 
hypothetical situation, were a new API was added). So, unless you definitely 
will not add APIs, the safe solution is to use

  -compatibility_version $(SHLIB_MAJOR)$(SHLIB_MINOR)

Which tells the linker that an executable which was linked against 7.1 cannot 
be used with version 7.0 of the library, but it can be used with 7.2, 7.3 etc.



Cheers,
Max

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail


reply via email to

[Prev in Thread] Current Thread [Next in Thread]