forked from apple/unityplugins
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupi_toolchain.py
More file actions
144 lines (115 loc) · 6.78 KB
/
upi_toolchain.py
File metadata and controls
144 lines (115 loc) · 6.78 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#! /usr/bin/env python3
# Requirements: python3
import scripts.python.upi_utility as utility
from collections.abc import Callable
from scripts.python.upi_utility import Printer
from scripts.python.upi_cli_argument_options import PlatformID
#--------------
# Build Helpers
# Invokes 'xcodebuild -version' and parses output for the associated Xcode version and build number
def GetToolchainVersions() -> tuple[str, str]:
xcode_version = ""
build_number = ""
version_output = utility.RunCommand(["xcodebuild", "-version"])
output_lines = version_output.stdout.split('\n')
for line in output_lines:
if line.startswith("Xcode"):
xcode_version = line.split(' ')[1]
elif line.startswith("Build"):
build_number = line.split(' ')[2]
return (xcode_version, build_number)
# Invokes 'xcodebuild -sdk -version' and searches the results for known SDK platform folder names.
# Returns a list of PlatformID representing the currently installed Apple platform SDKs
def GetSupportedPlatformList() -> list[str]:
# Use a set to ensure entries are unique; duplicates are possible. Ordering isn't important.
result = set()
sdk_version_output = utility.RunCommand(["xcodebuild", "-sdk", "-version"])
output_lines = sdk_version_output.stdout.split('\n')
for line in output_lines:
if "iPhoneOS.platform" in line:
result.add(PlatformID.IOS)
elif "AppleTVOS.platform" in line:
result.add(PlatformID.TVOS)
elif "MacOSX.platform" in line:
result.add(PlatformID.MACOS)
elif "XROS.platform" in line:
result.add(PlatformID.VISIONOS)
elif "iPhoneSimulator.platform" in line:
result.add(PlatformID.IOS_SIMULATOR)
elif "AppleTVSimulator.platform" in line:
result.add(PlatformID.TVOS_SIMULATOR)
elif "XRSimulator.platform" in line:
result.add(PlatformID.VISIONOS_SIMULATOR)
else:
continue
return list(result)
#-------------
# Code Signing
# Returns a dictionary of formatted output from a command line invocation of 'security find-identity -v -p codesigning', or an empty dictionary if no identities are found.
#
# This command returns a multi-line response which lists each identity found along with an additional line which summarizes the number of found identities
#
# Example output:
# 1) HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH "Title of identity: Developer Name (XXXXXXXXXX)"
# 1 valid identity found
#
# This method processes that output and returns a dictionary which contains the hash mapped to the identity name
# e.g.
# {'HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH' : '"Title of identity: Developer Name (XXXXXXXXXX)"', ...}
#
# Organizing the output dictionary in this manner provides an easy means of listing the full identity and retreiving just the hash without further parsing.
def GetCodesignIdentities() -> dict[str, str]:
security_command_output = utility.RunCommand(["security", "find-identity", "-v", "-p", "codesigning"])
output_lines = security_command_output.stdout.strip().split("\n")
codesign_identity_table = dict()
num_lines = len(output_lines)
if num_lines > 1:
for line_index in range(num_lines - 1):
# Remove leading/trailing white space
curr_output_line = output_lines[line_index].strip()
# Hash substring starts after the first space and runs to the second space
hash_start_index = curr_output_line.find(' ') + 1
hash_end_index = curr_output_line.find(' ', hash_start_index)
hash = curr_output_line[hash_start_index : hash_end_index]
# Codesign identity 'name' string consumes remaining portion of output string
identity_name = curr_output_line[hash_end_index + 1:]
codesign_identity_table[hash] = identity_name
return codesign_identity_table
# Performs codesigning on supplied object, such as a .framework or .bundle, using the supplied codesign identity hash.
# See: GetCodesignIdentities for querying codesign identities on the system.
def Codesign(printer : Printer, signable_object_path : str, hash : str, logWithContext : Callable[[str, str], None] = None) -> bool:
codesign_command = ["codesign", "--force", "--sign", hash, "--timestamp=none", "--preserve-metadata=identifier,entitlements,flags", "--generate-entitlement-der", f"{signable_object_path}"]
if logWithContext == None:
printer.MessageWithContext("Target object: ", signable_object_path)
printer.MessageWithContext("Codesign command: ", f"{' '.join(codesign_command)}")
else:
logWithContext("Target object: ", signable_object_path)
logWithContext("Codesign command: ", f"{' '.join(codesign_command)}")
codesign_command_output = utility.RunCommand(codesign_command)
if codesign_command_output.returncode != 0:
printer.ErrorMessage("Failed to perform codesign.")
printer.Message("Command Response:"
f"\n{codesign_command_output.stdout}")
return False
else:
return True
# Method prompts the user before identifying a codesign identity to use for signing newly compiled native plug-in libraries
def PromptForCodesignIdentity(printer : Printer) -> str:
if not utility.BooleanPrompt(printer, "Would you like the script to code sign the compiled native plug-in libraries?"):
printer.Message("User opted out of code signing.")
printer.Message(f"For more information about code signing, please see: {Printer.Bold('https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html')}", printer.Indent(1))
return ""
codesign_identities = GetCodesignIdentities()
if len(codesign_identities) == 0:
printer.WarningMessage("No codesign identities found.")
printer.Message(f"For more information about code signing, please see: {Printer.Bold('https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html')}", printer.Indent(1))
return ""
elif len(codesign_identities) == 1:
id_hash, id_name = list(codesign_identities.items())[0]
printer.InfoMessage("Only one codesign identity found.")
printer.MessageWithContext("Using codesign identity: ", f"{id_hash} {id_name}", "\n")
return id_hash
else:
id_hash, id_name = utility.SelectionPrompt(printer, "Multiple codesign identities found. Please select an identity to use for signing:", [(h, n) for (h, n) in codesign_identities.items()], display_func=lambda hn: f"{hn[0]} {hn[1]}")
printer.MessageWithContext("User selected codesign identity: ", f"{id_hash} {id_name}", "\n")
return id_hash