Skip to content

Commit 2ecae29

Browse files
dgovilthearperson
authored andcommitted
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 79e668e commit 2ecae29

3 files changed

Lines changed: 166 additions & 39 deletions

File tree

README.md

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

183-
##### MacOS:
183+
##### macOS:
184184

185185
In a terminal, run `xcode-select` to ensure command line developer tools are
186186
installed. Then run the script.
@@ -192,6 +192,16 @@ then build and install USD into `/path/to/my_usd_install_dir`.
192192
> python OpenUSD/build_scripts/build_usd.py /path/to/my_usd_install_dir
193193
```
194194

195+
###### iOS
196+
197+
When building from a macOS system, you can cross compile for iOS based platforms.
198+
199+
iOS builds currently do not support Imaging.
200+
Additionally, they will not support Python bindings or command line tools.
201+
202+
To build for iOS, add the `--build-target iOS` parameter.
203+
204+
195205
##### Windows:
196206

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

build_scripts/apple_utils.py

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,58 +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):
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):
120126
def 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+
128148
def 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

145166
devout = 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+
175233
def 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

Comments
 (0)