summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorL. E. Segovia <amy@centricular.com>2024-07-06 02:39:44 +0000
committerBackport Bot <gitlab-backport-bot@gstreamer-foundation.org>2024-07-09 22:24:06 +0200
commit12fdd2342097b5e350781a4811d9adad361ba22e (patch)
tree8355b713c219b8ee5911a6c573417afa2e441fd6
parent85194850e1f2e7836ac3c86b65074e1a520c6a29 (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-xcerbero/tools/osxrelocator.py23
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