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 ):
83- macTargets = None
86+ if context .buildTarget in EMBEDDED_PLATFORMS :
87+ return GetTargetArmArch ()
8488 if context .targetNative :
8589 macTargets = GetHostArch ()
8690 else :
8791 if context .targetX86 :
8892 macTargets = TARGET_X86
89- if context .targetARM64 :
93+ if context .targetARM64 or context . buildTarget in EMBEDDED_PLATFORMS :
9094 macTargets = GetTargetArmArch ()
9195 if context .targetUniversal :
9296 macTargets = TARGET_X86 + ";" + GetTargetArmArch ()
@@ -108,6 +112,8 @@ def GetTargetArchPair(context):
108112 primaryArch = TARGET_X86
109113 if context .targetARM64 :
110114 primaryArch = GetTargetArmArch ()
115+ if context .buildTarget in EMBEDDED_PLATFORMS :
116+ primaryArch = GetTargetArmArch ()
111117 if context .targetUniversal :
112118 primaryArch = GetHostArch ()
113119 if (primaryArch == TARGET_X86 ):
@@ -120,18 +126,33 @@ def GetTargetArchPair(context):
120126def SupportsMacOSUniversalBinaries ():
121127 if not MacOS ():
122128 return False
123- XcodeOutput = GetCommandOutput (' /usr/bin/xcodebuild -version' )
129+ XcodeOutput = GetCommandOutput ([ " /usr/bin/xcodebuild" , " -version" ] )
124130 XcodeFind = XcodeOutput .rfind ('Xcode ' , 0 , len (XcodeOutput ))
125131 XcodeVersion = XcodeOutput [XcodeFind :].split (' ' )[1 ]
126132 return (XcodeVersion > '11.0' )
127133
134+
135+ def GetSDKRoot (context ) -> Optional [str ]:
136+ sdk = "macosx"
137+ if context .buildTarget == TARGET_IOS :
138+ sdk = "iphoneos"
139+
140+ for arg in (context .cmakeBuildArgs or '' ).split ():
141+ if "CMAKE_OSX_SYSROOT" in arg :
142+ override = arg .split ('=' )[1 ].strip ('"' ).strip ()
143+ if override :
144+ sdk = override
145+ return GetCommandOutput (["xcrun" , "--sdk" , sdk , "--show-sdk-path" ])
146+
147+
128148def SetTarget (context , targetName ):
129149 context .targetNative = (targetName == TARGET_NATIVE )
130150 context .targetX86 = (targetName == TARGET_X86 )
131151 context .targetARM64 = (targetName == GetTargetArmArch ())
132152 context .targetUniversal = (targetName == TARGET_UNIVERSAL )
153+ context .targetIos = (targetName == TARGET_IOS )
133154 if context .targetUniversal and not SupportsMacOSUniversalBinaries ():
134- self .targetUniversal = False
155+ context .targetUniversal = False
135156 raise ValueError (
136157 "Universal binaries only supported in macOS 11.0 and later." )
137158
@@ -140,7 +161,7 @@ def GetTargetName(context):
140161 TARGET_X86 if context .targetX86 else
141162 GetTargetArmArch () if context .targetARM64 else
142163 TARGET_UNIVERSAL if context .targetUniversal else
143- "" )
164+ context . buildTarget )
144165
145166devout = open (os .devnull , 'w' )
146167
@@ -152,26 +173,63 @@ def ExtractFilesRecursive(path, cond):
152173 files .append (os .path .join (r , file ))
153174 return files
154175
155- def CodesignFiles (files ):
156- SDKVersion = subprocess .check_output (
157- ['xcodebuild' , '-version' ]).strip ()[6 :10 ]
158- codeSignIDs = subprocess .check_output (
159- ['security' , 'find-identity' , '-vp' , 'codesigning' ])
176+ def _GetCodeSignStringFromTerminal ():
177+ codeSignIDs = GetCommandOutput (['security' , 'find-identity' , '-vp' , 'codesigning' ])
178+ return codeSignIDs
160179
161- codeSignID = "-"
180+ def GetCodeSignID ():
162181 if os .environ .get ('CODE_SIGN_ID' ):
163- codeSignID = os .environ .get ('CODE_SIGN_ID' )
164- elif float (SDKVersion ) >= 11.0 and \
165- codeSignIDs .find (b'Apple Development' ) != - 1 :
166- codeSignID = "Apple Development"
167- elif codeSignIDs .find (b'Mac Developer' ) != - 1 :
168- codeSignID = "Mac Developer"
182+ return os .environ .get ('CODE_SIGN_ID' )
183+
184+ codeSignIDs = _GetCodeSignStringFromTerminal ()
185+ if not codeSignIDs :
186+ return "-"
187+ for codeSignID in codeSignIDs .splitlines ():
188+ if "CSSMERR_TP_CERT_REVOKED" in codeSignID :
189+ continue
190+ if ")" not in codeSignID :
191+ continue
192+ codeSignID = codeSignID .split ()[1 ]
193+ break
194+ else :
195+ raise RuntimeError ("Could not find a valid codesigning ID" )
196+
197+ return codeSignID or "-"
198+
199+ def GetCodeSignIDHash ():
200+ codeSignIDs = _GetCodeSignStringFromTerminal ()
201+ try :
202+ return re .findall (r'\(.*?\)' , codeSignIDs )[0 ][1 :- 1 ]
203+ except :
204+ raise Exception ("Unable to parse codesign ID hash" )
205+
206+ def GetDevelopmentTeamID ():
207+ if os .environ .get ("DEVELOPMENT_TEAM" ):
208+ return os .environ .get ("DEVELOPMENT_TEAM" )
209+ codesignID = GetCodeSignIDHash ()
210+
211+ certs = subprocess .check_output (["security" , "find-certificate" , "-c" , codesignID , "-p" ])
212+ subject = GetCommandOutput (["openssl" , "x509" , "-subject" ], input = certs )
213+ subject = subject .splitlines ()[0 ]
214+
215+ # Extract the Organizational Unit (OU field) from the cert
216+ try :
217+ team = [elm for elm in subject .split (
218+ '/' ) if elm .startswith ('OU' )][0 ].split ('=' )[1 ]
219+ if team is not None and team != "" :
220+ return team
221+ except Exception as ex :
222+ raise Exception ("No development team found with exception " + ex )
223+
224+ def CodesignFiles (files ):
225+ codeSignID = GetCodeSignID ()
169226
170227 for f in files :
171228 subprocess .call (['codesign' , '-f' , '-s' , '{codesignid}'
172- .format (codesignid = codeSignID ), f ],
229+ .format (codesignid = codeSignID ), f ],
173230 stdout = devout , stderr = devout )
174231
232+
175233def Codesign (install_path , verbose_output = False ):
176234 if not MacOS ():
177235 return False
@@ -219,3 +277,19 @@ def CreateUniversalBinaries(context, libNames, x86Dir, armDir):
219277 instDir = context .instDir , libName = targetName ),
220278 outputName )
221279 return lipoCommands
280+
281+ def ConfigureCMakeExtraArgs (context , args :List [str ]) -> List [str ]:
282+ system_name = None
283+ if context .buildTarget == TARGET_IOS :
284+ system_name = "iOS"
285+
286+ if system_name :
287+ args .append (f"-DCMAKE_SYSTEM_NAME={ system_name } " )
288+ args .append (f"-DCMAKE_OSX_SYSROOT={ GetSDKRoot (context )} " )
289+
290+ # CMake gets confused trying to find things when setting the system name
291+ # See https://discourse.cmake.org/t/find-package-stops-working-when-cmake-system-name-ios/4609/8
292+ args .append (f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH" )
293+ args .append (f"-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH" )
294+ args .append (f"-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH" )
295+ return args
0 commit comments