[MacPorts] #62426: libc++: using a newer libc++ to build software on older macos systems
MacPorts
noreply at macports.org
Wed Sep 21 10:23:33 UTC 2022
#62426: libc++: using a newer libc++ to build software on older macos systems
-------------------------------------+--------------------
Reporter: kencu | Owner: kencu
Type: enhancement | Status: closed
Priority: Normal | Milestone:
Component: ports | Version:
Resolution: fixed | Keywords:
Port: libcxx macports-libcxx |
-------------------------------------+--------------------
Comment (by RJVB):
Well, not exactly; in my scenario executable A is linked against
$prefix/lib/libc++.dylib (not newlibc++.dylib). If these were frameworks
then dyld might indeed use the bundle ID or some similar metadata to
recognise two libraries as identical (except for version), REGARDLESS of
their filename.
The whole idea behind shared libraries that I know of is that the dynamic
loader (dyld on Darwin) will consider each linked library but only load it
if it resolves as-yet-unresolved symbols. And even then it will only load
the symbols that were not yet resolved.
On Darwin with its compatibility_version and current_version metadata
embedded in the dylibs the linker could also decide to prioritise multiple
copies by version - this I don't know.
As far as I can see this is really no different than forcing the loader to
use a different library by using DYLD_INSERT_LIBRARIES (or LD_PRELOAD on
Linux). You must be familiar with libraries that override `malloc()` and
family; that's the same principle even if this involves an add-on library.
Jemalloc for instance (`port:jemalloc`) can be used 2 ways: either you
link your executable with it, or you insert/preload/inject it.
There is one scenario where the above could go wrong. If dyld first
encounters a shared library that depends on /usr/lib/libc++ (or indeed if
the executable itself depends on that), the scenario painted above may be
reversed, and then code built with newer libc++ headers (in some other
dependency) would be executed against the older libc++ binary
implementation.
I *think* there are 2 protections against that:
- setting the current_version info (in which case at worst dyld will print
an error and abort execution)
- setting DYLD_INSERT_LIBRARIES=$prefix/lib/libc++.dylib
That latter suggestion might also be interesting to try in known cases
where having a newer libc++ causes problems.
I do realise that there would be a number of practical issues to sort out
if MacPorts were ever to provide libc++.dylib (and I do mean not just
libc++.1.dylib!) directly in $prefix/lib. A priori you'd want to rebuild
every installed port.
Or relink. This is a bit thinking ahead, but I know "base" has at least
one mechanism to alter installed files (renaming conflicting files). The
rev-upgrade scanner can be used to find all binaries that depend on
/usr/lib/libc++.1.dylib, which can then be modified to depend on
$prefix/lib/libc++.1.dylib . Advanced magic, but it should work.
A last consideration: on Linux a lot of this would be automatic, provided
$prefix/lib corresponds to one of the standard (or configured/customised!)
library search paths, because it (mostly) lacks the possibility to
hardcode absolute library paths in binaries.
--
Ticket URL: <https://trac.macports.org/ticket/62426#comment:52>
MacPorts <https://www.macports.org/>
Ports system for macOS
More information about the macports-tickets
mailing list