Shared libraries created on Mac lack version info and have the wrong ID #59
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Shared libraries on Mac have 2 versions stored inside: a current version and a compatibility (aka ABI) version. This information is stored in dependents linked against those libraries, and the loader will refuse to load a dependent if a dependency is replaced with one having a lower compatibility version.
Also, each shared library has a so-called id, and under normal linking conditions this information is also stored in the dependents to allow to find/load the intended copy of the dependency.
From a fresh rlibtool-based build of pkgconf and comparing with the installed version:
You'll note that the freshly built library has 0.0.0 for both versions, which means any dependent that has been linked against the installed version will fail to load after installing that new version.
In addition, any dependent linked against the new version will expect
libpkgconf.4.0.0.dylibin./.libs, probably meaning a .libs subdirectory of the directory where the dependent lives. And it would fail to load after a pkgconf upgrade replacedlibpkgconf.4.0.0.dylibwith saylibpkgconf.4.0.1.dylib.My last 2 reported issues are real blockers, which is sad because it seemed like rlibtool became ready for prime time and it can really help speeding builds up on Mac.
That should still be the case if rlibtool could be configured to delegate static and shared library generation to the project's
libtoolscript if it exists, as a more or less temporary workaround for projects that "don't build yet". Does that option already exist or how hard would it be to implement?@midipix I believe Darwin requires
-Wl,-install_name,libfoo.@MAJOR_VERSION@.dylibwhereMAJOR_VERSIONis a number of course while linux uses-soname.@midipix Just in you case you don't already know, on Darwin
-no-undefinedshould set-Wl,-undefined,error.Thanks @RJVB and @orbea! The above info surely will make fixing easy. To be continued ...
Yes.
-install_nameshould take care of setting the proper ID in the library, but with libtool's approach it may be necessary to change this during the install phase when the dylibs are moved from their.libdirectory to the ultimate install location. I admit I didn't look at the-install_namearguments emitted, just at the final results.I wasn't aware there's an Apple version of
--no-undefined(but I think it's the default behaviour).@RJVB I am not sure if this helps, but a lot of these were tested for the GNU Makefile in this gambatte fork.
gitlab.com/jgemu/gambatte/-@5fe2c023bd/mk/jg.mk (L32-60)Using the git version and building using
make install-sharedshould install Darwin libraries with correct library name and version? This is what I am using for reference.almost, almost there ...
Can you attach the full build report, starting with ./configure? That'll help speed things up:-)
Here you go:
Here's the libtool script too; it seems likely that it'll have the additional arguments to set the compatibility and current version values.
Fixed in commit
816e2809f4:=)I believe commit
5d0af4bacccovers everything in terms of-sonamevs.-install_name, but perhaps more string transformations are needed.I'll need to test on my Mac, but out of curiosity: why do you do the platform testing at runtime? I suppose in case of cross-compiling, but would that be done using tools from the host platform configure to generate Mach-O binaries but still requiring the native commandline options?
And I think #
816e280missed the-Wl,--no-undefinedinsrc/logic/linkcmd/slbt_linkcmd_executable.c;)Cross-compilation indeed :=)
Thanks for the catch! Now fixed in commit
d2d5afeab5.What I didn't catch is that
host = "x86_64-apple-darwin13.4.0"and that you probably meant to checkhost.flavor...EDIT:
with that suggested change the build now completes, but sadly you didn't address the other, trickier problems covered by this ticket:
Looking at what I think is the libtool invocation to create libpkconf:
While after a build using the project's libtool script:
Note how the output file is
.libs/libpkgconf.4.dylib, and the-install_name /opt/local/lib/libpkgconf.4.dylib -compatibility_version 5 -current_version 5.0which take care of setting the ID and versions.(There's also a
-Wl,-single_moduleof which I'm not certain if it's required.)Guilty as charged. Fixed in commit
36d22a5a10.We aim for commits to be as limited in scope as possible ... and when a single issue entails multiple points then several commits are to be expected:-)
And here's the difference:
From rlibtool's to libtool's link command, if I read the diff correctly?
Yes; what I do not understand is why both -soname and -install_name are missing from the rlibtool command. Following commits
5d0af4baccand36d22a5a10, that seems odd.Another oddity:
Is all I can see in the [r]libtool invocation in terms of version information, yet libtool passes the following:
Where is the '5' coming from? Can you see in gnu libtool where the math is taking place?
These are documented in the Darwin LD(1) man page.
https://www.unix.com/man-page/osx/1/ld/
But I am not sure where the '5' is coming from either.
I've given up trying to figure out GNU/libtool's version logic a long time ago.
A long-standing problem (on Mac) with code that migrates from autoconf to, say, Meson is that all libraries get the embedded versioning that's equal to the one in the filename ... and that dependents all have to be rebuilt even if there's no ABI change at all. And whatever reason GNU had to "be smart" with the version numbers it wasn't so important that it was carried over to the Meson build system.
We should find out if GNU had good reasons or not, Meson also failed to carry over basic things like
datarootdir...According to this old comment libtool did
n+1so that is presumably where the '5' comes from.https://github.com/mesonbuild/meson/issues/1451#issuecomment-284845913=
Which can be seen in
/usr/bin/libtool:And for
-install_name/usr/bin/libtoolshows:For reference this is what cmake seems to do:
github.com/Kitware/CMake@cc58d74388/Modules/Platform/Darwin.cmake (L54-L56)github.com/Kitware/CMake@cc58d74388/Modules/Platform/Darwin.cmake (L80-L81)github.com/Kitware/CMake@cc58d74388/Modules/Platform/Darwin.cmake (L97-L98)github.com/Kitware/CMake@cc58d74388/Source/cmGlobalXCodeGenerator.cxx (L3038-L3067)I think the verdict is that GNU libtool does
-compatibility_version $(($current + 1))and-current_version $(($current + 1)).$revision.While cmake gives them both
$major.$minor.$patchas long as the value is at least1.0.0.Looking at the various
.cmakefiles it seems some environment may require-Wl,while others do not. I am not sure if there are any that break if-Wl,is used?I think it's obvious that
rlibtoolshould do withlibtooldoes, for the reasons explained above. I'm not really up to speed with the intentions forslibtool; it could be preferable to do whatcmake(andmeson) do, ifslibtoolis not supposed to give the same build results aslibtool.Are you certain that this doesn't depend on which driver is used, i.e. whether clang is being invoked, or ld directly? The latter surely wouldn't like seeing
-Wl,.Agreed.
Not sure:
Indeed:-)
Since there are only a few switches left and they're all related, for now I'd like to get darwin support completed via a single commit. I'll post a patch in the next couple of days for @RJVB to test ...
@RJVB still waiting for your input and testing here and on #6, thanks!