diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2024-03-24 02:15:09 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2024-03-24 03:15:33 +0530 |
commit | 7aef890e474921ed7882417f233173a8398f1bed (patch) | |
tree | cbbc861ad9b9e3c17c8f3129770159c8dd4a0cb1 | |
parent | bb1e5e7f7a7c1732a42e0a24553cc6063d7f44a3 (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.py | 78 |
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)) |