3535import platform
3636import shlex
3737import subprocess
38+ import re
3839
3940TARGET_NATIVE = "native"
4041TARGET_X86 = "x86_64"
4142TARGET_ARM64 = "arm64"
4243TARGET_UNIVERSAL = "universal"
44+ TARGET_IOS = "ios"
4345
4446def GetBuildTargets ():
4547 return [TARGET_NATIVE ,
4648 TARGET_X86 ,
4749 TARGET_ARM64 ,
48- TARGET_UNIVERSAL ]
50+ TARGET_UNIVERSAL ,
51+ TARGET_IOS ]
4952
5053def GetBuildTargetDefault ():
5154 return TARGET_NATIVE ;
@@ -57,14 +60,52 @@ def GetLocale():
5760 return sys .stdout .encoding or locale .getdefaultlocale ()[1 ] or "UTF-8"
5861
5962def GetCommandOutput (command ):
60- """Executes the specified command and returns output or None."""
63+ """Executes the specified command and returns output or None.
64+ If command contains pipes (i.e '|'s), creates a subprocess for
65+ each pipe in command, returning the output from the last subcommand
66+ or None if any of the subcommands result in a CalledProcessError"""
67+
68+ result = None
69+
70+ args = shlex .split (command )
71+ commands = []
72+ cmd_args = []
73+ while args :
74+ arg = args .pop (0 )
75+ if arg == '|' :
76+ commands .append ((cmd_args ))
77+ cmd_args = []
78+ else :
79+ cmd_args .append (arg )
80+ commands .append ((cmd_args ))
81+
82+ pipes = []
83+ while len (commands ) > 1 :
84+ # We have some pipes
85+ command = commands .pop (0 )
86+ stdin = pipes [- 1 ].stdout if pipes else None
87+ try :
88+ pipe = subprocess .Popen (command , stdin = stdin , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
89+ pipes .append (pipe )
90+ except subprocess .CalledProcessError :
91+ return None
92+
93+ # The last command actually returns a result
94+ command = commands [0 ]
6195 try :
62- return subprocess .check_output (
63- shlex .split (command ),
64- stderr = subprocess .STDOUT ).decode (GetLocale (), 'replace' ).strip ()
96+ stdin = pipes [- 1 ].stdout if pipes else None
97+ result = subprocess .check_output (
98+ command ,
99+ stdin = stdin ,
100+ stderr = subprocess .STDOUT ).decode ('utf-8' ).strip ()
65101 except subprocess .CalledProcessError :
66102 pass
67- return None
103+
104+ # clean-up
105+ for pipe in pipes :
106+ pipe .wait ()
107+
108+ return result
68109
69110def GetTargetArmArch ():
70111 # Allows the arm architecture string to be overridden by
@@ -85,7 +126,7 @@ def GetTargetArch(context):
85126 else :
86127 if context .targetX86 :
87128 macTargets = TARGET_X86
88- if context .targetARM64 :
129+ if context .targetARM64 or context . targetIos :
89130 macTargets = GetTargetArmArch ()
90131 if context .targetUniversal :
91132 macTargets = TARGET_X86 + ";" + GetTargetArmArch ()
@@ -106,6 +147,8 @@ def GetTargetArchPair(context):
106147 primaryArch = TARGET_X86
107148 if context .targetARM64 :
108149 primaryArch = GetTargetArmArch ()
150+ if context .targetIos :
151+ primaryArch = TARGET_IOS
109152 if context .targetUniversal :
110153 primaryArch = GetHostArch ()
111154 if (primaryArch == TARGET_X86 ):
@@ -128,6 +171,17 @@ def SetTarget(context, targetName):
128171 context .targetX86 = (targetName == TARGET_X86 )
129172 context .targetARM64 = (targetName == GetTargetArmArch ())
130173 context .targetUniversal = (targetName == TARGET_UNIVERSAL )
174+ context .targetIos = (targetName == TARGET_IOS )
175+ if context .targetIos :
176+ sdkStr = GetCommandOutput ('xcodebuild -showsdks' )
177+ sdkStrSpl = sdkStr .split ()
178+ for s in sdkStrSpl :
179+ if s .startswith ('iphoneos' ):
180+ s = s .replace ('iphoneos' , "" )
181+ context .iosVersion = s
182+ break
183+ else :
184+ context .iosVersion = None
131185 if context .targetUniversal and not SupportsMacOSUniversalBinaries ():
132186 self .targetUniversal = False
133187 raise ValueError (
@@ -138,6 +192,7 @@ def GetTargetName(context):
138192 TARGET_X86 if context .targetX86 else
139193 GetTargetArmArch () if context .targetARM64 else
140194 TARGET_UNIVERSAL if context .targetUniversal else
195+ TARGET_IOS if context .targetIos else
141196 "" )
142197
143198devout = open (os .devnull , 'w' )
@@ -150,26 +205,54 @@ def ExtractFilesRecursive(path, cond):
150205 files .append (os .path .join (r , file ))
151206 return files
152207
153- def CodesignFiles (files ):
154- SDKVersion = subprocess .check_output (
155- ['xcodebuild' , '-version' ]).strip ()[6 :10 ]
156- codeSignIDs = subprocess .check_output (
157- ['security' , 'find-identity' , '-vp' , 'codesigning' ])
208+ def _GetCodeSignStringFromTerminal ():
209+ codeSignIDs = subprocess .check_output (['security' ,
210+ 'find-identity' , '-vp' , 'codesigning' ])
211+ return codeSignIDs
158212
213+ def GetCodeSignID ():
214+ codeSignIDs = _GetCodeSignStringFromTerminal ()
159215 codeSignID = "-"
160216 if os .environ .get ('CODE_SIGN_ID' ):
161217 codeSignID = os .environ .get ('CODE_SIGN_ID' )
162- elif float (SDKVersion ) >= 11.0 and \
163- codeSignIDs .find (b'Apple Development' ) != - 1 :
164- codeSignID = "Apple Development"
165- elif codeSignIDs .find (b'Mac Developer' ) != - 1 :
166- codeSignID = "Mac Developer"
218+ else :
219+ try :
220+ codeSignID = codeSignIDs .decode ("utf-8" ).split ()[1 ]
221+ except :
222+ raise Exception ("Unable to parse codesign ID" )
223+ return codeSignID
224+
225+ def GetCodeSignIDHash ():
226+ codeSignIDs = _GetCodeSignStringFromTerminal ()
227+ try :
228+ return re .findall (r'\(.*?\)' , codeSignIDs .decode ("utf-8" ))[0 ][1 :- 1 ]
229+ except :
230+ raise Exception ("Unable to parse codesign ID hash" )
231+
232+ def GetDevelopmentTeamID ():
233+ if os .environ .get ("DEVELOPMENT_TEAM" ):
234+ return os .environ .get ("DEVELOPMENT_TEAM" )
235+ codesignID = GetCodeSignIDHash ()
236+ x509subject = GetCommandOutput ('security find-certificate -c {}'
237+ ' -p | openssl x509 -subject | head -1' .format (codesignID )).strip ()
238+ # Extract the Organizational Unit (OU field) from the cert
239+ try :
240+ team = [elm for elm in x509subject .split (
241+ '/' ) if elm .startswith ('OU' )][0 ].split ('=' )[1 ]
242+ if team is not None and team != "" :
243+ return team
244+ except Exception as ex :
245+ raise Exception ("No development team found with exception " + ex )
246+
247+ def CodesignFiles (files ):
248+ codeSignID = GetCodeSignID ()
167249
168250 for f in files :
169251 subprocess .call (['codesign' , '-f' , '-s' , '{codesignid}'
170- .format (codesignid = codeSignID ), f ],
252+ .format (codesignid = codeSignID ), f ],
171253 stdout = devout , stderr = devout )
172254
255+
173256def Codesign (install_path , verbose_output = False ):
174257 if not MacOS ():
175258 return False
0 commit comments