[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
signature.asc
Description: Message signed with OpenPGP using GPGMail
- Re: [Bug-readline] Set correct -compatibility_version in .dylib on Mac OS X,
Max Horn <=