diff options
author | L. E. Segovia <amy@centricular.com> | 2024-07-06 02:39:44 +0000 |
---|---|---|
committer | Backport Bot <gitlab-backport-bot@gstreamer-foundation.org> | 2024-07-09 22:24:06 +0200 |
commit | 12fdd2342097b5e350781a4811d9adad361ba22e (patch) | |
tree | 8355b713c219b8ee5911a6c573417afa2e441fd6 | |
parent | 85194850e1f2e7836ac3c86b65074e1a520c6a29 (diff) |
osxrelocator: Fix framework entrypoints being unable to load dylibs
This is unexpected fallout from !1478 and !1485. It was reported on the
GStreamer Matrix room that GStreamer.framework would not either load or,
once its RPATH is manually inserted, it would refuse to forward any of
the reexported dylibs.
This is because of two reasons:
- the framework is generated as `<cerbero dist folder>/lib/GStreamer`,
then repacked (post having been relocated and merged as a normal lib)
- the framework entrypoint is already relocatable, so once OSXRelocator
touches it, its relocatable, working dylib ID is replaced with a
"correct" (for a lib) but broken one
This commit works around it by validating the dylib ID and skipping it
if it's already relocatable, and adding the relevant RPATHs.
Part-of: <https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/1508>
-rwxr-xr-x | cerbero/tools/osxrelocator.py | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/cerbero/tools/osxrelocator.py b/cerbero/tools/osxrelocator.py index 42fb44bf..449b31e1 100755 --- a/cerbero/tools/osxrelocator.py +++ b/cerbero/tools/osxrelocator.py @@ -19,6 +19,7 @@ import os +from cerbero.errors import FatalError from cerbero.utils import shell @@ -84,11 +85,21 @@ class OSXRelocator(object): # points to the real ID of this library # This used to be done only at Universal lipo time, but by then # it's too late -- unless one wants to run through all load commands - self.change_id(object_file, id='@rpath/{}'.format(os.path.basename(original_file))) + # If the library isn't a dylib, it's a framework, in which case + # assert that it's already rpath'd + dylib_id = self.get_dylib_id(object_file) + is_dylib = dylib_id is not None + is_framework = is_dylib and not object_file.endswith('.dylib') + if not is_framework: + self.change_id(object_file, id='@rpath/{}'.format(os.path.basename(original_file))) + elif '@rpath' not in dylib_id: + raise FatalError(f'Cannot relocate a fixed location framework: {dylib_id}') # With that out of the way, we need to sort out how many parents # need to be navigated to reach the root of the GStreamer prefix depth = len(original_file.split('/')) - len(self.lib_prefix.split('/')) p_depth = '/..' * depth + # These paths assume that the file being relocated resides within + # <GStreamer root>/lib rpaths = [ # From a deeply nested library f'@loader_path{p_depth}/lib', @@ -105,6 +116,11 @@ class OSXRelocator(object): '@loader_path/..', '@executable_path/..', ] + if is_framework: + # Start with framework's libraries + rpaths = [ + '@loader_path/lib', + ] + rpaths # Make them unique rpaths = list(set(rpaths)) # Remove absolute RPATHs, we don't want or need these @@ -145,6 +161,11 @@ class OSXRelocator(object): break @staticmethod + def get_dylib_id(object_file): + res = shell.check_output([OTOOL_CMD, '-D', object_file]).splitlines() + return res[-1] if len(res) > 1 else None + + @staticmethod def list_shared_libraries(object_file): res = shell.check_output([OTOOL_CMD, '-L', object_file]).splitlines() # We don't use the first line |