|
| 1 | +""" |
| 2 | +Postprocess binaries on CI |
| 3 | +""" |
| 4 | + |
| 5 | +# TODO: We need a proper way to identify and sign bundles. Unfortunately Apple does not make this easy. |
| 6 | + |
| 7 | +import subprocess |
| 8 | +import sys |
| 9 | +from pathlib import Path |
| 10 | + |
| 11 | +# Configurable options |
| 12 | + |
| 13 | +IDENTITY = "hackdoc" |
| 14 | +TARGET_DIR = Path("Universal-Binaries") |
| 15 | +UNUSED = [ |
| 16 | + # Mojave and Catalina non-Metal Patches |
| 17 | + # No longer used by us, but nice for reference |
| 18 | + "10.13.6-18", |
| 19 | + "10.13.6-19", |
| 20 | + "10.14.4-18", |
| 21 | + "10.14.4-19", |
| 22 | + "10.14.6-19", |
| 23 | + # Nvidia Web Driver Patches |
| 24 | + # Remove .pkg, unused by patcher |
| 25 | + "WebDriver-387.10.10.10.40.140/WebDriver-387.10.10.10.40.140.pkg", |
| 26 | + "WebDriver-387.10.10.10.40.140/WebDriver-387.10.10.15.15.108.pkg", |
| 27 | +] |
| 28 | + |
| 29 | +# Constants |
| 30 | + |
| 31 | +MACHO_MAGIC = { |
| 32 | + "MH_MAGIC": b"\xfe\xed\xfa\xce", |
| 33 | + "MH_CIGAM": b"\xce\xfa\xed\xfe", |
| 34 | + "MH_MAGIC_64": b"\xfe\xed\xfa\xcf", |
| 35 | + "MH_CIGAM_64": b"\xcf\xfa\xed\xfe", |
| 36 | + "FAT_MAGIC": b"\xbe\xba\xfe\xca", |
| 37 | + "FAT_CIGAM": b"\xca\xfe\xba\xbe", |
| 38 | +} |
| 39 | + |
| 40 | + |
| 41 | +def clean_unused(): |
| 42 | + """ |
| 43 | + Remove unused files and folders |
| 44 | + """ |
| 45 | + |
| 46 | + for path in UNUSED: |
| 47 | + path = TARGET_DIR / path |
| 48 | + if path.exists(): |
| 49 | + print(f"Removing: {path}") |
| 50 | + subprocess.check_output(["rm", "-rf", path]) |
| 51 | + |
| 52 | + for path in TARGET_DIR.rglob(".DS_Store"): |
| 53 | + print(f"Removing: {path}") |
| 54 | + path.unlink() |
| 55 | + |
| 56 | + |
| 57 | +def get_machos(directory=TARGET_DIR): |
| 58 | + """ |
| 59 | + Get all machos in a directory |
| 60 | + """ |
| 61 | + |
| 62 | + machos: dict[Path, bytes] = {} |
| 63 | + for file in directory.rglob("*"): |
| 64 | + if not file.is_file() or file.is_symlink(): |
| 65 | + continue |
| 66 | + with file.open("rb") as f: |
| 67 | + magic = f.read(4) |
| 68 | + if magic in MACHO_MAGIC.values(): |
| 69 | + machos[file] = magic |
| 70 | + return dict(sorted(machos.items(), key=lambda item: item[0])) |
| 71 | + |
| 72 | + |
| 73 | +def thin_macho(file: Path, magic: bytes): |
| 74 | + """ |
| 75 | + Run lipo to thin a fat macho |
| 76 | + """ |
| 77 | + |
| 78 | + if magic in (MACHO_MAGIC["FAT_MAGIC"], MACHO_MAGIC["FAT_CIGAM"]): |
| 79 | + subprocess.check_output(["lipo", "-thin", "x86_64", "-output", file, file]) |
| 80 | + |
| 81 | + |
| 82 | +if __name__ == "__main__": |
| 83 | + clean_unused() |
| 84 | + machos = get_machos() |
| 85 | + if not machos: |
| 86 | + print("No machos found!") |
| 87 | + sys.exit(1) |
| 88 | + for macho, magic in machos.items(): |
| 89 | + thin_macho(macho, magic) |
| 90 | + print("Done!") |
0 commit comments