From 4ee9e142899fd6cdd5fdd939283b5c826138a53b Mon Sep 17 00:00:00 2001 From: Cameron White Date: Tue, 31 Dec 2024 13:14:09 -0500 Subject: [PATCH] Update the bundle_gtk script to work with the arm64 homebrew install prefix --- installer/macos/build_installer.sh | 2 +- installer/macos/bundle_gtk.py | 75 ++++++++++++++++++------------ 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/installer/macos/build_installer.sh b/installer/macos/build_installer.sh index 2945fd4cc3..d6495f23f8 100755 --- a/installer/macos/build_installer.sh +++ b/installer/macos/build_installer.sh @@ -40,7 +40,7 @@ cp pinta.icns ${MAC_APP_DIR}/Contents/Resources # Install the GTK dependencies. echo "Bundling GTK..." -./bundle_gtk.py --resource_dir ${MAC_APP_RESOURCE_DIR} +./bundle_gtk.py --runtime $runtimeid --resource_dir ${MAC_APP_RESOURCE_DIR} # Add the GTK lib dir to the library search path (for dlopen()), as an alternative to $DYLD_LIBRARY_PATH. install_name_tool -add_rpath "@executable_path/../Resources/lib" ${MAC_APP_BIN_DIR}/Pinta diff --git a/installer/macos/bundle_gtk.py b/installer/macos/bundle_gtk.py index 0dd2ef695d..6071a4f92a 100755 --- a/installer/macos/bundle_gtk.py +++ b/installer/macos/bundle_gtk.py @@ -8,25 +8,18 @@ import subprocess from stat import S_IREAD, S_IRGRP, S_IROTH, S_IWUSR -PREFIX = "/usr/local" - # Grab all dependencies of libadwaita / libgtk, plus pixbuf loader plugins. -GTK_LIB = "/usr/local/lib/libadwaita-1.0.dylib" -RSVG_LIB = "/usr/local/lib/librsvg-2.2.dylib" -TIFF_LIB = "/usr/local/lib/libtiff.6.dylib" -WEBP_DEMUX_LIB = "/usr/local/lib/libwebpdemux.2.dylib" -WEBP_MUX_LIB = "/usr/local/lib/libwebpmux.3.dylib" +GTK_LIB = "lib/libadwaita-1.0.dylib" +RSVG_LIB = "lib/librsvg-2.2.dylib" +TIFF_LIB = "lib/libtiff.6.dylib" +WEBP_DEMUX_LIB = "lib/libwebpdemux.2.dylib" +WEBP_MUX_LIB = "lib/libwebpmux.3.dylib" ROOT_LIBS = [GTK_LIB, RSVG_LIB, TIFF_LIB, WEBP_DEMUX_LIB, WEBP_MUX_LIB] -ADWAITA_THEME = "/usr/local/share/icons/Adwaita/index.theme" +ADWAITA_THEME = "share/icons/Adwaita/index.theme" PIXBUF_LOADERS = "lib/gdk-pixbuf-2.0/2.10.0" GLIB_SCHEMAS = "share/glib-2.0/schemas" -# Match against non-system libraries -OTOOL_LIB_REGEX = re.compile(r"(/usr/local/.*\.dylib)") -# Match against relative paths (webp and related libraries) -OTOOL_REL_LIB_REGEX = re.compile(r"@rpath/(lib.*\.dylib)") - def run_install_name_tool(lib, deps, lib_install_dir): # Make writable by user. @@ -40,22 +33,22 @@ def run_install_name_tool(lib, deps, lib_install_dir): dep_lib = "@executable_path/../Resources/lib/" + dep_lib_name cmd = ['install_name_tool', '-change', dep_path, dep_lib, - '-change', f"@rpath/{dep_path_basename}", dep_lib, # For libraries like webp + '-change', f"@rpath/{dep_path_basename}", dep_lib, # For libraries like webp lib] subprocess.check_output(cmd) -def collect_libs(src_lib, lib_deps): +def collect_libs(src_lib, lib_deps, otool_lib_regex, otool_rel_lib_regex): """ Use otool -L to collect the library dependencies. """ cmd = ['otool', '-L', src_lib] output = subprocess.check_output(cmd).decode('utf-8') - referenced_paths = re.findall(OTOOL_LIB_REGEX, output) + referenced_paths = re.findall(otool_lib_regex, output) folder = os.path.dirname(src_lib) referenced_paths.extend([os.path.join(folder, lib) - for lib in re.findall(OTOOL_REL_LIB_REGEX, output)]) + for lib in re.findall(otool_rel_lib_regex, output)]) real_lib_paths = set([os.path.realpath(lib) for lib in referenced_paths]) @@ -63,26 +56,26 @@ def collect_libs(src_lib, lib_deps): for lib in real_lib_paths: if lib not in lib_deps: - collect_libs(lib, lib_deps) + collect_libs(lib, lib_deps, otool_lib_regex, otool_rel_lib_regex) -def copy_resources(res_path): +def copy_resources(src_prefix, res_path): """ Copy a folder from ${PREFIX}/${res_path} to Contents/Resources/${res_path}. """ dest_folder = os.path.join(args.resource_dir, res_path) - shutil.copytree(os.path.join(PREFIX, res_path), + shutil.copytree(os.path.join(src_prefix, res_path), dest_folder, dirs_exist_ok=True) -def copy_plugins(res_path, lib_install_dir): +def copy_plugins(src_prefix, res_path, lib_install_dir, otool_lib_regex, otool_rel_lib_regex): """ Copy a folder of plugins from ${PREFIX}/${res_path} to Contents/Resources/${res_path} and update the library references. """ - copy_resources(res_path) + copy_resources(src_prefix, res_path) # Update paths to the main GTK libs. lib_install_dir = os.path.join(args.resource_dir, 'lib') @@ -94,17 +87,18 @@ def copy_plugins(res_path, lib_install_dir): lib_path = os.path.join(root, lib) lib_deps = {} - collect_libs(lib_path, lib_deps) + collect_libs(lib_path, lib_deps, otool_lib_regex, + otool_rel_lib_regex) run_install_name_tool(lib_path, lib_deps[lib_path], lib_install_dir) -def install_plugin_cache(cache_path, resource_dir): +def install_plugin_cache(src_prefix, cache_path, resource_dir): """ Copy a file such as immodules.cache, and update the library paths to be paths inside the .app bundle. """ - src_cache = os.path.join(PREFIX, cache_path) + src_cache = os.path.join(src_prefix, cache_path) dest_cache = os.path.join(resource_dir, cache_path) with open(src_cache, 'r') as src_f: @@ -117,15 +111,31 @@ def install_plugin_cache(cache_path, resource_dir): parser = argparse.ArgumentParser(description='Bundle the GTK libraries.') +parser.add_argument('--runtime', type=str, required=True, + help='The dotnet runtime id, e.g. osx-x64 or osx-arm64') parser.add_argument('--resource_dir', type=pathlib.Path, required=True, help='Directory to copy extra resources to.') args = parser.parse_args() +src_prefix = "" +if args.runtime == "osx-x64": + src_prefix = "/usr/local" +elif args.runtime == "osx-arm64": + src_prefix = "/opt/homebrew" +else: + raise RuntimeError("Invalid runtime id") + +# Match against non-system libraries +otool_lib_regex = re.compile(fr"({src_prefix}/.*\.dylib)") +# Match against relative paths (webp and related libraries) +otool_rel_lib_regex = re.compile(r"@rpath/(lib.*\.dylib)") + lib_deps = {} for root_lib in ROOT_LIBS: - collect_libs(os.path.realpath(root_lib), lib_deps) + lib_path = os.path.realpath(os.path.join(src_prefix, root_lib)) + collect_libs(lib_path, lib_deps, otool_lib_regex, otool_rel_lib_regex) lib_install_dir = os.path.join(args.resource_dir, 'lib') os.makedirs(lib_install_dir) @@ -139,18 +149,21 @@ def install_plugin_cache(cache_path, resource_dir): os.path.join(lib_install_dir, "libgdk_pixbuf-2.0.dylib")) # Copy translations and icons. -gtk_root = os.path.join(os.path.dirname(os.path.realpath(GTK_LIB)), "..") +gtk_root = os.path.join(os.path.dirname( + os.path.realpath(os.path.join(src_prefix, GTK_LIB))), "..") shutil.copytree(os.path.join(gtk_root, 'share/locale'), os.path.join(args.resource_dir, 'share/locale'), dirs_exist_ok=True) # TODO - could probably trim the number of installed icons. -adwaita_icons = os.path.join(os.path.dirname(os.path.realpath(ADWAITA_THEME)), "..") +adwaita_icons = os.path.join(os.path.dirname( + os.path.realpath(os.path.join(src_prefix, ADWAITA_THEME))), "..") shutil.copytree(adwaita_icons, os.path.join(args.resource_dir, 'share/icons'), dirs_exist_ok=True) -copy_plugins(PIXBUF_LOADERS, lib_install_dir) -install_plugin_cache(os.path.join(PIXBUF_LOADERS, "loaders.cache"), +copy_plugins(src_prefix, PIXBUF_LOADERS, lib_install_dir, + otool_lib_regex, otool_rel_lib_regex) +install_plugin_cache(src_prefix, os.path.join(PIXBUF_LOADERS, "loaders.cache"), args.resource_dir) -copy_resources(GLIB_SCHEMAS) +copy_resources(src_prefix, GLIB_SCHEMAS)