summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2024-03-24 02:15:09 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2024-03-24 03:15:33 +0530
commit7aef890e474921ed7882417f233173a8398f1bed (patch)
treecbbc861ad9b9e3c17c8f3129770159c8dd4a0cb1
parentbb1e5e7f7a7c1732a42e0a24553cc6063d7f44a3 (diff)
cerbero: Need to relocate Mach-O install names and paths
Code copied from cerbero/tools/osxrelocator.py Part-of: <https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/1423>
-rw-r--r--cerbero/commands/cache.py78
1 files changed, 68 insertions, 10 deletions
diff --git a/cerbero/commands/cache.py b/cerbero/commands/cache.py
index 0cae283d..5b7b02ae 100644
--- a/cerbero/commands/cache.py
+++ b/cerbero/commands/cache.py
@@ -173,6 +173,73 @@ class FetchCache(BaseCache):
m.warning(f'Did not find cache for commit {sha}')
return None
+ @staticmethod
+ def _is_mach_o_file(filename):
+ fileext = os.path.splitext(filename)[1]
+ if '.dylib' in fileext:
+ return True
+ filedesc = shell.check_output(['file', '-bh', filename])
+ if fileext == '.a' and 'ar archive' in filedesc:
+ return False
+ return filedesc.startswith('Mach-O')
+
+ @staticmethod
+ def _list_shared_libraries(object_file):
+ res = shell.check_output(['otool', '-L', object_file]).splitlines()
+ # We don't use the first line
+ libs = res[1:]
+ # Remove the first character tabulation
+ libs = [x[1:] for x in libs]
+ # Remove the version info
+ libs = [x.split(' ', 1)[0] for x in libs]
+ return libs
+
+ @classmethod
+ def _change_lib_paths(self, object_file, old_path, new_path):
+ for lib in self._list_shared_libraries(object_file):
+ if old_path not in lib:
+ continue
+ new = lib.replace(old_path, new_path)
+ cmd = ['install_name_tool', '-change', lib, new, object_file]
+ shell.new_call(cmd, fail=True, verbose=True)
+
+ def relocate_macos_build_tools(self, config, old_path, new_path):
+ """
+ build-tools on macOS have absolute paths as install names for all
+ Mach-O files, so we need to relocate them to the new prefix.
+ The Universal build isn't affected because Cerbero relocates the
+ binaries there.
+ """
+ paths = [
+ os.path.join(config.build_tools_prefix, 'bin'),
+ os.path.join(config.build_tools_prefix, 'lib'),
+ ]
+ for dir_path in paths:
+ for dirpath, _dirnames, filenames in os.walk(dir_path):
+ for f in filenames:
+ object_file = os.path.join(dirpath, f)
+ if not self._is_mach_o_file(object_file):
+ continue
+ self._change_lib_paths(object_file, old_path, new_path)
+
+ def relocate_prefix(self, config, namespace):
+ """
+ We need to relocate pc files that weren't generated by meson and
+ python programs installed with pip because the shebang set by the
+ virtualenv python uses an absolute path.
+ """
+ origin = self.get_cache_home_dir(config, namespace)
+ dest = config.home_dir
+ if origin == dest:
+ return
+ m.action(f'Relocating text files from {origin} to {dest}')
+ sed = self.get_gnu_sed(config)
+ # This is hacky, but fast enough
+ shell.call(f'grep -lrIe {origin} {dest} | xargs {sed} "s#{origin}#{dest}#g" -i', verbose=True)
+ # Need to relocate RPATHs and names in binaries
+ if config.platform == Platform.DARWIN:
+ self.relocate_macos_build_tools(config, origin, dest)
+
async def fetch_dep(self, config, dep, namespace):
is_ci = 'CI' in os.environ
try:
@@ -187,16 +254,7 @@ class FetchCache(BaseCache):
m.action('Unpack complete, deleting artifact')
os.remove(dep_path)
- # We need to relocate pc files that weren't generated by meson and
- # python programs installed with pip because the shebang set by the
- # virtualenv python uses an absolute path.
- origin = self.get_cache_home_dir(config, namespace)
- dest = config.home_dir
- if origin != dest:
- m.action(f'Relocating text files from {origin} to {dest}')
- sed = self.get_gnu_sed(config)
- # This is hacky, but fast enough
- shell.call(f'grep -lrIe {origin} {dest} | xargs {sed} "s#{origin}#{dest}#g" -i', verbose=True)
+ self.relocate_prefix(config, namespace)
except FatalError as e:
m.warning('Could not retrieve dependencies for commit %s: %s' % (dep['commit'], e.msg))