3535import platform
3636import shlex
3737import subprocess
38+ import re
39+ from typing import Optional , List
3840
3941TARGET_NATIVE = "native"
4042TARGET_X86 = "x86_64"
4143TARGET_ARM64 = "arm64"
4244TARGET_UNIVERSAL = "universal"
45+ TARGET_IOS = "iOS"
46+
47+ EMBEDDED_PLATFORMS = [TARGET_IOS ]
4348
4449def GetBuildTargets ():
4550 return [TARGET_NATIVE ,
4651 TARGET_X86 ,
4752 TARGET_ARM64 ,
48- TARGET_UNIVERSAL ]
53+ TARGET_UNIVERSAL ,
54+ TARGET_IOS ]
4955
5056def GetBuildTargetDefault ():
51- return TARGET_NATIVE ;
57+ return TARGET_NATIVE
5258
5359def MacOS ():
5460 return platform .system () == "Darwin"
5561
5662def GetLocale ():
5763 return sys .stdout .encoding or locale .getdefaultlocale ()[1 ] or "UTF-8"
5864
59- def GetCommandOutput (command ):
65+ def GetCommandOutput (command , ** kwargs ):
6066 """Executes the specified command and returns output or None."""
6167 try :
62- return subprocess .check_output (
63- shlex .split (command ),
64- stderr = subprocess .STDOUT ).decode (GetLocale (), 'replace' ).strip ()
65- except subprocess .CalledProcessError :
66- pass
67- return None
68+ return subprocess .check_output (command , stderr = subprocess .STDOUT , ** kwargs ).decode (GetLocale (), 'replace' ).strip ()
69+ except :
70+ return None
6871
6972def GetTargetArmArch ():
7073 # Allows the arm architecture string to be overridden by
7174 # setting MACOS_ARM_ARCHITECTURE
7275 return os .environ .get ('MACOS_ARM_ARCHITECTURE' ) or TARGET_ARM64
7376
7477def GetHostArch ():
75- macArch = GetCommandOutput (' arch' ). strip ( )
78+ macArch = GetCommandOutput ([ " arch" ] )
7679 if macArch == "i386" or macArch == TARGET_X86 :
7780 macArch = TARGET_X86
7881 else :
7982 macArch = GetTargetArmArch ()
8083 return macArch
8184
8285def GetTargetArch (context ):
86+ if context .buildTarget in EMBEDDED_PLATFORMS :
87+ return GetTargetArmArch ()
8388 if context .targetNative :
8489 macTargets = GetHostArch ()
8590 else :
8691 if context .targetX86 :
8792 macTargets = TARGET_X86
88- if context .targetARM64 :
93+ if context .targetARM64 or context . buildTarget in EMBEDDED_PLATFORMS :
8994 macTargets = GetTargetArmArch ()
9095 if context .targetUniversal :
9196 macTargets = TARGET_X86 + ";" + GetTargetArmArch ()
@@ -106,6 +111,8 @@ def GetTargetArchPair(context):
106111 primaryArch = TARGET_X86
107112 if context .targetARM64 :
108113 primaryArch = GetTargetArmArch ()
114+ if context .buildTarget in EMBEDDED_PLATFORMS :
115+ primaryArch = GetTargetArmArch ()
109116 if context .targetUniversal :
110117 primaryArch = GetHostArch ()
111118 if (primaryArch == TARGET_X86 ):
@@ -118,18 +125,33 @@ def GetTargetArchPair(context):
118125def SupportsMacOSUniversalBinaries ():
119126 if not MacOS ():
120127 return False
121- XcodeOutput = GetCommandOutput (' /usr/bin/xcodebuild -version' )
128+ XcodeOutput = GetCommandOutput ([ " /usr/bin/xcodebuild" , " -version" ] )
122129 XcodeFind = XcodeOutput .rfind ('Xcode ' , 0 , len (XcodeOutput ))
123130 XcodeVersion = XcodeOutput [XcodeFind :].split (' ' )[1 ]
124131 return (XcodeVersion > '11.0' )
125132
133+
134+ def GetSDKRoot (context ) -> Optional [str ]:
135+ sdk = "macosx"
136+ if context .buildTarget == TARGET_IOS :
137+ sdk = "iphoneos"
138+
139+ for arg in (context .cmakeBuildArgs or '' ).split ():
140+ if "CMAKE_OSX_SYSROOT" in arg :
141+ override = arg .split ('=' )[1 ].strip ('"' ).strip ()
142+ if override :
143+ sdk = override
144+ return GetCommandOutput (["xcrun" , "--sdk" , sdk , "--show-sdk-path" ])
145+
146+
126147def SetTarget (context , targetName ):
127148 context .targetNative = (targetName == TARGET_NATIVE )
128149 context .targetX86 = (targetName == TARGET_X86 )
129150 context .targetARM64 = (targetName == GetTargetArmArch ())
130151 context .targetUniversal = (targetName == TARGET_UNIVERSAL )
152+ context .targetIos = (targetName == TARGET_IOS )
131153 if context .targetUniversal and not SupportsMacOSUniversalBinaries ():
132- self .targetUniversal = False
154+ context .targetUniversal = False
133155 raise ValueError (
134156 "Universal binaries only supported in macOS 11.0 and later." )
135157
@@ -138,7 +160,7 @@ def GetTargetName(context):
138160 TARGET_X86 if context .targetX86 else
139161 GetTargetArmArch () if context .targetARM64 else
140162 TARGET_UNIVERSAL if context .targetUniversal else
141- "" )
163+ context . buildTarget )
142164
143165devout = open (os .devnull , 'w' )
144166
@@ -150,26 +172,63 @@ def ExtractFilesRecursive(path, cond):
150172 files .append (os .path .join (r , file ))
151173 return files
152174
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' ])
175+ def _GetCodeSignStringFromTerminal ():
176+ codeSignIDs = GetCommandOutput (['security' , 'find-identity' , '-vp' , 'codesigning' ])
177+ return codeSignIDs
158178
159- codeSignID = "-"
179+ def GetCodeSignID ():
160180 if os .environ .get ('CODE_SIGN_ID' ):
161- 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"
181+ return os .environ .get ('CODE_SIGN_ID' )
182+
183+ codeSignIDs = _GetCodeSignStringFromTerminal ()
184+ if not codeSignIDs :
185+ return "-"
186+ for codeSignID in codeSignIDs .splitlines ():
187+ if "CSSMERR_TP_CERT_REVOKED" in codeSignID :
188+ continue
189+ if ")" not in codeSignID :
190+ continue
191+ codeSignID = codeSignID .split ()[1 ]
192+ break
193+ else :
194+ raise RuntimeError ("Could not find a valid codesigning ID" )
195+
196+ return codeSignID or "-"
197+
198+ def GetCodeSignIDHash ():
199+ codeSignIDs = _GetCodeSignStringFromTerminal ()
200+ try :
201+ return re .findall (r'\(.*?\)' , codeSignIDs )[0 ][1 :- 1 ]
202+ except :
203+ raise Exception ("Unable to parse codesign ID hash" )
204+
205+ def GetDevelopmentTeamID ():
206+ if os .environ .get ("DEVELOPMENT_TEAM" ):
207+ return os .environ .get ("DEVELOPMENT_TEAM" )
208+ codesignID = GetCodeSignIDHash ()
209+
210+ certs = subprocess .check_output (["security" , "find-certificate" , "-c" , codesignID , "-p" ])
211+ subject = GetCommandOutput (["openssl" , "x509" , "-subject" ], input = certs )
212+ subject = subject .splitlines ()[0 ]
213+
214+ # Extract the Organizational Unit (OU field) from the cert
215+ try :
216+ team = [elm for elm in subject .split (
217+ '/' ) if elm .startswith ('OU' )][0 ].split ('=' )[1 ]
218+ if team is not None and team != "" :
219+ return team
220+ except Exception as ex :
221+ raise Exception ("No development team found with exception " + ex )
222+
223+ def CodesignFiles (files ):
224+ codeSignID = GetCodeSignID ()
167225
168226 for f in files :
169227 subprocess .call (['codesign' , '-f' , '-s' , '{codesignid}'
170- .format (codesignid = codeSignID ), f ],
228+ .format (codesignid = codeSignID ), f ],
171229 stdout = devout , stderr = devout )
172230
231+
173232def Codesign (install_path , verbose_output = False ):
174233 if not MacOS ():
175234 return False
@@ -217,3 +276,12 @@ def CreateUniversalBinaries(context, libNames, x86Dir, armDir):
217276 instDir = context .instDir , libName = targetName ),
218277 outputName )
219278 return lipoCommands
279+
280+ def ConfigureCMakeExtraArgs (context , args :List [str ]) -> List [str ]:
281+ system_name = None
282+ if context .buildTarget == TARGET_IOS :
283+ system_name = "iOS"
284+
285+ if system_name :
286+ args .append (f"-DCMAKE_SYSTEM_NAME={ system_name } " )
287+ return args
0 commit comments