Skip to content

Commit cad5058

Browse files
committed
Add iOS build support for USD Core
This PR adds **Core** iOS support to the OpenUSD project. This does not include Imaging, and any Imaging related components at this time. Imaging will be added in a follow up PR. MaterialX is also disabled as requested and the upgrade will be handled in a follow up PR. It is a minimal version of PixarAnimationStudios#2455 against the latest `dev` branch. Changes include: * Using latest dev branch * No imaging support. Will be added in a follow up PR. * Makes use of CMake's inbuilt iOS support, negating the need for toolchain support * Structures the code in such a way that we can add support for other iOS derived platforms+simulator in future PRs * Swaps `ARCH_OS_IOS` with `ARCH_OS_IPHONE` to align with compiler directives. IPHONE refers to all derivative platforms, whereas iOS refers to only iPhone/iPad (Confusing but the case for historical reasons as [documented here](https://chaosinmotion.com/2021/08/02/things-to-remember-compiler-conditionals-for-macos-ios-etc/)) * TBB requires SDKROOT to be passed in or it can often go off and find some random compiler toolchain and fail. * Add APPLE_EMBEDDED boolean to designate when using the CMake supported cross compilation targets. Added in Options.cmake so it can be used to configure defaults properly.
1 parent 328e504 commit cad5058

3 files changed

Lines changed: 166 additions & 38 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ then build and install USD into `/path/to/my_usd_install_dir`.
129129
> python OpenUSD/build_scripts/build_usd.py /path/to/my_usd_install_dir
130130
```
131131

132-
##### MacOS:
132+
##### macOS:
133133

134134
In a terminal, run `xcode-select` to ensure command line developer tools are
135135
installed. Then run the script.
@@ -141,6 +141,16 @@ then build and install USD into `/path/to/my_usd_install_dir`.
141141
> python OpenUSD/build_scripts/build_usd.py /path/to/my_usd_install_dir
142142
```
143143

144+
###### iOS
145+
146+
When building from a macOS system, you can cross compile for iOS based platforms.
147+
148+
iOS builds currently do not support Imaging.
149+
Additionally, they will not support Python bindings or command line tools.
150+
151+
To build for iOS, add the `--build-target iOS` parameter.
152+
153+
144154
##### Windows:
145155

146156
Launch the "x64 Native Tools Command Prompt" for your version of Visual Studio

build_scripts/apple_utils.py

Lines changed: 102 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,57 +35,62 @@
3535
import platform
3636
import shlex
3737
import subprocess
38+
import re
39+
from typing import Optional, List
3840

3941
TARGET_NATIVE = "native"
4042
TARGET_X86 = "x86_64"
4143
TARGET_ARM64 = "arm64"
4244
TARGET_UNIVERSAL = "universal"
45+
TARGET_IOS = "iOS"
46+
47+
EMBEDDED_PLATFORMS = [TARGET_IOS]
4348

4449
def GetBuildTargets():
4550
return [TARGET_NATIVE,
4651
TARGET_X86,
4752
TARGET_ARM64,
48-
TARGET_UNIVERSAL]
53+
TARGET_UNIVERSAL,
54+
TARGET_IOS]
4955

5056
def GetBuildTargetDefault():
51-
return TARGET_NATIVE;
57+
return TARGET_NATIVE
5258

5359
def MacOS():
5460
return platform.system() == "Darwin"
5561

5662
def 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

6972
def 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

7477
def 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

8285
def 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):
118125
def 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+
126147
def 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

143165
devout = 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+
173232
def Codesign(install_path, verbose_output=False):
174233
if not MacOS():
175234
return False
@@ -217,3 +276,19 @@ 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+
args.append(f"-DCMAKE_OSX_SYSROOT={GetSDKRoot(context)}")
288+
289+
# CMake gets confused trying to find things when setting the system name
290+
# See https://discourse.cmake.org/t/find-package-stops-working-when-cmake-system-name-ios/4609/8
291+
args.append(f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH")
292+
args.append(f"-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=BOTH")
293+
args.append(f"-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=BOTH")
294+
return args

0 commit comments

Comments
 (0)