| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- #!/usr/bin/env python
- import sys
- import os
- import subprocess
- # A general note: We first produce a x86_64 and a arm64 app package
- # and then merge them together instead of compiling the desktop client
- # with the CMake option CMAKE_OSX_ARCHITECTURES="x86_64;arm64" because
- # macdeployqt can not handle universal binaries well. In the future
- # with Qt6 this might change and this script will become obsolete.
- def usage(program_name):
- print("Creates a universal app package from a x86_64 and a arm64 app package.")
- print("Usage: {} x86_64_app_file arm64_app_file output_directory".format(program_name))
- print("Example: {} some_dir/Nextcloud.app some_other_dir/Nextcloud.app output_dir".format(program_name))
- def execute(command):
- return subprocess.check_output(command)
- def path_relative_to_package(app_package_file_path, file_path):
- if file_path.startswith(app_package_file_path):
- relative_path = file_path[len(app_package_file_path):]
- if relative_path.startswith("/"):
- return relative_path[1:]
- return relative_path
- return file_path
- def is_executable(file_path):
- output = str(execute(["file", file_path]))
- if (("Mach-O 64-bit dynamically linked shared library" in output)
- or ("Mach-O 64-bit executable" in output)):
- return True
- return False
- if __name__ == "__main__":
- if len(sys.argv) != 4:
- usage(sys.argv[0])
- sys.exit(1)
- x86_64_app_file = sys.argv[1]
- if not os.path.exists(x86_64_app_file):
- print("Can't create universal: Path {} does not exist".format(x86_64_app_file))
- sys.exit(1)
- arm64_app_file = sys.argv[2]
- if not os.path.exists(arm64_app_file):
- print("Can't create universal: Path {} does not exist".format(arm64_app_file))
- sys.exit(1)
- output_dir = sys.argv[3]
- # Copy the Arm64 variant to the output location if possible
- if not os.path.exists(output_dir):
- os.makedirs(output_dir)
- app_file_name = os.path.basename(arm64_app_file)
- universal_app_file = os.path.join(output_dir, app_file_name)
- if os.path.exists(universal_app_file):
- print("Can't create universal: Path {} already exists".format(universal_app_file))
- sys.exit(1)
- execute(["cp", "-a", arm64_app_file, output_dir])
- # Now walk through the copied arm64 version and replace the binaries
- for root, dirs, files in os.walk(universal_app_file):
- for f in files:
- absolute_file_path = os.path.join(root, f)
- root_relative = path_relative_to_package(universal_app_file, root)
- x86_64_absolute_path = os.path.join(x86_64_app_file, root_relative, f)
- arm64_absolute_path = os.path.join(arm64_app_file, root_relative, f)
- if os.path.islink(absolute_file_path) or not is_executable(absolute_file_path):
- continue
- try:
- print(f"Going to merge {arm64_absolute_path} with {x86_64_absolute_path} into {absolute_file_path}")
- execute(["lipo", "-create", "-output", absolute_file_path, arm64_absolute_path, x86_64_absolute_path])
- print(execute(["lipo", "-info", absolute_file_path]))
- except:
- print(f"Could not merge {arm64_absolute_path} with {x86_64_absolute_path} into {absolute_file_path}!")
- print("Finished :)")
|