diff --git a/scripts/fix_app_bundle_paths.py b/scripts/fix_app_bundle_paths.py index f35444c..fda4c9d 100755 --- a/scripts/fix_app_bundle_paths.py +++ b/scripts/fix_app_bundle_paths.py @@ -10,49 +10,38 @@ class AppBundleChecker: - def __init__(self): - # Get command line arguments - args = self.parse_args() - self.app_path = os.path.join(os.getcwd(), args.app) - - # Determine the exectutable to check - files = os.listdir(os.path.join(self.app_path, 'Contents/MacOS')) - # assumes only one executable in MacOS dir, which I think is standard - # for mac apps - self.executable_path = os.path.join(self.app_path, 'Contents/MacOS', - files[0]) - # Set the frameworks path - self.frameworks_path = os.path.join(self.app_path, - "Contents/Frameworks") - # Set the plugins path - self.plugins_path = os.path.join(self.app_path, - "Contents/PlugIns") + def __init__(self, app, brew_prefix=None, app_path_override=False): + if app_path_override: + # supply exact app path to check, and use its directory directly + # for all dependencies. + app_path = os.path.dirname(app) + self.app_path = app_path + self.frameworks_path = app_path + self.plugins_path = app_path + # assuming only file present yet is the executable + self.executable_path = app + else: + self.app_path = os.path.join(os.getcwd(), app) + # Determine the exectutable to check + files = os.listdir(os.path.join(self.app_path, 'Contents/MacOS')) + # assumes only one executable in MacOS dir, which I think is standard + # for mac apps + self.executable_path = os.path.join(self.app_path, 'Contents/MacOS', + files[0]) + # Set the frameworks path + self.frameworks_path = os.path.join(self.app_path, + "Contents/Frameworks") + # Set the plugins path + self.plugins_path = os.path.join(self.app_path, + "Contents/PlugIns") # Find the homebrew path - brew_prefix = args.brew_prefix if not brew_prefix: brew_prefix = "/opt/homebrew" if not (os.path.exists(brew_prefix)): brew_prefix = "/usr/local" self.homebrew_path = brew_prefix + '/opt' - def parse_args(self): - """ Instantiate a command line argument parser """ - - # Define command line arguments which can be provided - parser = argparse.ArgumentParser( - description="Check for Library paths missed by macdeployqt in" + - "MAC .app bundles") - parser.add_argument( - '--app', type=str, required=True, - help='relative path to .app bundle') - parser.add_argument('--brew_prefix', type=str, default=None, help="homebrew prefix") - - # Parse the command line arguments - args = parser.parse_args() - - return args - def check(self): # check app itself self.check_executable(self.executable_path) @@ -122,8 +111,9 @@ def fix_library_path(self, library_path, referenced_from): self.add_library_to_app(library_name) # always need to update reference print("Updating reference: ", library_name) + new_library_path = self.get_new_library_path() subprocess.run(["install_name_tool", "-change", library_path, - "@executable_path/../Frameworks/" + library_name, + new_library_path + library_name, referenced_from]) def exists_in_app(self, lib): @@ -141,6 +131,8 @@ def add_library_to_app(self, library_name): print(src, " is a framework") new_library_path = self.frameworks_path + "/" + library_name self.update_self_references(library_name, new_library_path, src) + # if this library just got added, run check_executable on it too + self.check_executable(new_library_path) def add_framework_to_app(self, framework_name): framework_dir = Path(framework_name).parts[0] @@ -167,17 +159,42 @@ def update_self_references(self, name, new_path, old_path): # update ID and self-reference of a file that has just been added to # the app bundle # update ID of file just copied + new_library_path = self.get_new_library_path() subprocess.run(["install_name_tool", "-id", - "@executable_path/../Frameworks/" + name, + new_library_path + name, new_path]) # update self-reference of file just copied subprocess.run(["install_name_tool", "-change", old_path, - "@executable_path/../Frameworks/" + name, + new_library_path + name, new_path]) + + def get_new_library_path(self): + new_library_path = "@executable_path/../Frameworks/" + if self.frameworks_path == self.app_path: # no app bundle structure + new_library_path = "@executable_path/" + return new_library_path + +def parse_args(): + """ Instantiate a command line argument parser """ + + # Define command line arguments which can be provided + parser = argparse.ArgumentParser( + description="Check for Library paths missed by macdeployqt in" + + "MAC .app bundles") + parser.add_argument( + '--app', type=str, required=True, + help='relative path to .app bundle') + parser.add_argument('--brew_prefix', type=str, default=None, help="homebrew prefix") + + # Parse the command line arguments + args = parser.parse_args() + + return args def main(): - checker = AppBundleChecker() + args = parse_args() + checker = AppBundleChecker(args.app, args.brew_prefix) checker.check()