Welcome to mirror list, hosted at ThFree Co, Russian Federation.

make_universal.py « osx « admin - github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: abc6e671fbc7efde91f3017647b66495c53c9431 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/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 {} already exists".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 {} already exists".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:
            absoulte_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(absoulte_file_path) or not is_executable(absoulte_file_path):
                continue
            try:
                execute(["lipo", "-create", "-output", absoulte_file_path, arm64_absolute_path, x86_64_absolute_path])
            except:
                print("Could not merge {} with {} into {}!".format(arm64_absolute_path, x86_64_absolute_path, absoulte_file_path))

    print("Finished :)")