From e64a948edd429cd39a5ddf2a1d4c5c5e58307697 Mon Sep 17 00:00:00 2001 From: akrieger Date: Mon, 29 Jan 2024 03:45:17 -0800 Subject: [PATCH] Use dylibbundler to copy and resign libs for native arm64 builds. (#71314) Co-authored-by: Andrew Krieger --- .github/workflows/release.yml | 2 +- Makefile | 2 +- tools/copy_mac_libs.py | 94 ----------------------------------- 3 files changed, 2 insertions(+), 96 deletions(-) delete mode 100644 tools/copy_mac_libs.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd1675badaad0..bb87f34eed786 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -232,7 +232,7 @@ jobs: - name: Install build dependencies (mac) if: runner.os == 'macOS' run: | - HOMEBREW_NO_AUTO_UPDATE=yes HOMEBREW_NO_INSTALL_CLEANUP=yes brew install gettext ccache parallel + HOMEBREW_NO_AUTO_UPDATE=yes HOMEBREW_NO_INSTALL_CLEANUP=yes brew install gettext ccache parallel dylibbundler pip3 install dmgbuild biplist - name: Create VERSION.TXT shell: bash diff --git a/Makefile b/Makefile index 09808691d98e0..f486363ad2ff3 100644 --- a/Makefile +++ b/Makefile @@ -1244,7 +1244,7 @@ endif # ifdef FRAMEWORK endif # ifdef TILES ifndef FRAMEWORK - python3 ./tools/copy_mac_libs.py $(APPRESOURCESDIR)/$(APPTARGET) + dylibbundler -of -b -x $(APPRESOURCESDIR)/$(APPTARGET) -d $(APPRESOURCESDIR)/ -p @executable_path/ endif # ifndef FRAMEWORK diff --git a/tools/copy_mac_libs.py b/tools/copy_mac_libs.py deleted file mode 100644 index d35859dec8491..0000000000000 --- a/tools/copy_mac_libs.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python3 -import os -import shutil -import stat -import subprocess -import sys - -executable = "" -executable_dir = "" -copied_dependencies = [] - - -def is_homebrew_library(library): - homebrew_locations = ["/usr/local/opt", "/opt/homebrew"] - for homebrew_location in homebrew_locations: - if homebrew_location in library: - return True - return False - - -def rewrite_identity(object): - shutil.chown(object, os.getuid()) - st = os.stat(object) - os.chmod(object, st.st_mode | stat.S_IWUSR) - id = "@executable_path/{}".format(os.path.basename(object)) - ret = subprocess.run(["install_name_tool", "-id", id, object]) - if ret.returncode != 0: - print("Error:", ret.stderr.decode('utf-8')) - os.chmod(object, (st.st_mode | stat.S_IWUSR) ^ stat.S_IWUSR) - print("Rewritten identity of {}".format(object)) - - -def rewrite_dependency(object, dependency): - shutil.chown(object, os.getuid()) - st = os.stat(object) - os.chmod(object, st.st_mode | stat.S_IWUSR) - dest = "@executable_path/{}".format(os.path.basename(dependency)) - ret = subprocess.run(["install_name_tool", "-change", dependency, - dest, object]) - if ret.returncode != 0: - print("Error:", ret.stderr.decode('utf-8')) - os.chmod(object, (st.st_mode | stat.S_IWUSR) ^ stat.S_IWUSR) - print("Rewritten reference from {} to {}".format(dependency, dest)) - - -def copy_and_rewrite(file): - global executable - global executable_dir - if not os.path.isfile(file): - # raise Exception("{} is not a file.".format(executable)) - return [] - otool_ret = subprocess.run(["otool", "-L", file], capture_output=True) - if otool_ret.returncode != 0: - raise Exception("An error occurred in calling otool -L:\n {}" - .format(otool_ret.stderr.decode('utf-8'))) - dependencies = [] - for line in otool_ret.stdout.decode('utf-8').split('\n')[1:]: - line = line.strip() - if len(line) == 0 or line.find(" (compatibility version") == -1: - continue - library = os.path.abspath(line[0:line.find(" (compatibility version")]) - if is_homebrew_library(library): - dependencies.append(library) - copied_file = file - if file != executable: - copied_file = shutil.copy2(file, executable_dir) - print("Copied {} to {}".format(file, copied_file)) - for dependency in dependencies: - if dependency == file: - rewrite_identity(copied_file) - else: - rewrite_dependency(copied_file, dependency) - if dependency not in copied_dependencies: - copied_dependencies.append(dependency) - copy_and_rewrite(dependency) - - -def main(): - if len(sys.argv) < 2: - print("Usage: python3 ./tools/copy_mac_libs.py ") - return 1 - if not os.path.isfile(sys.argv[1]): - print(sys.argv[1], "is not a file.") - return 1 - global executable - global executable_dir - executable = os.path.abspath(sys.argv[1]) - executable_dir = os.path.dirname(executable) - print("Executable Dir =", executable_dir) - copy_and_rewrite(executable) - return 0 - - -exit(main())