Skip to content

Commit 7fe3958

Browse files
committed
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 #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. This PR requires #2947 to be merged first as that allows for not requiring Boost patches per platform, which can get fragile.
1 parent fe7067c commit 7fe3958

12 files changed

Lines changed: 207 additions & 58 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 USD/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 USD/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: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,44 +35,46 @@
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):
60-
"""Executes the specified command and returns output or None."""
65+
def GetCommandOutput(command, **kwargs):
6166
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
67+
return subprocess.check_output(command, stderr=subprocess.STDOUT, **kwargs).decode(GetLocale(), 'replace').strip()
68+
except:
69+
return None
6870

6971
def GetTargetArmArch():
7072
# Allows the arm architecture string to be overridden by
7173
# setting MACOS_ARM_ARCHITECTURE
7274
return os.environ.get('MACOS_ARM_ARCHITECTURE') or TARGET_ARM64
7375

7476
def GetHostArch():
75-
macArch = GetCommandOutput('arch').strip()
77+
macArch = GetCommandOutput(["arch"])
7678
if macArch == "i386" or macArch == TARGET_X86:
7779
macArch = TARGET_X86
7880
else:
@@ -85,7 +87,7 @@ def GetTargetArch(context):
8587
else:
8688
if context.targetX86:
8789
macTargets = TARGET_X86
88-
if context.targetARM64:
90+
if context.targetARM64 or context.targetIos:
8991
macTargets = GetTargetArmArch()
9092
if context.targetUniversal:
9193
macTargets = TARGET_X86 + ";" + GetTargetArmArch()
@@ -106,6 +108,8 @@ def GetTargetArchPair(context):
106108
primaryArch = TARGET_X86
107109
if context.targetARM64:
108110
primaryArch = GetTargetArmArch()
111+
if context.targetIos:
112+
primaryArch = TARGET_IOS
109113
if context.targetUniversal:
110114
primaryArch = GetHostArch()
111115
if (primaryArch == TARGET_X86):
@@ -118,18 +122,33 @@ def GetTargetArchPair(context):
118122
def SupportsMacOSUniversalBinaries():
119123
if not MacOS():
120124
return False
121-
XcodeOutput = GetCommandOutput('/usr/bin/xcodebuild -version')
125+
XcodeOutput = GetCommandOutput(["/usr/bin/xcodebuild", "-version"])
122126
XcodeFind = XcodeOutput.rfind('Xcode ', 0, len(XcodeOutput))
123127
XcodeVersion = XcodeOutput[XcodeFind:].split(' ')[1]
124128
return (XcodeVersion > '11.0')
125129

130+
131+
def GetSDKRoot(context) -> Optional[str]:
132+
sdk = "macosx"
133+
if context.buildTarget == TARGET_IOS:
134+
sdk = "iphoneos"
135+
136+
for arg in (context.cmakeBuildArgs or '').split():
137+
if "CMAKE_OSX_SYSROOT" in arg:
138+
override = arg.split('=')[1].strip('"').strip()
139+
if override:
140+
sdk = override
141+
return GetCommandOutput(["xcrun", "--sdk", sdk, "--show-sdk-path"])
142+
143+
126144
def SetTarget(context, targetName):
127145
context.targetNative = (targetName == TARGET_NATIVE)
128146
context.targetX86 = (targetName == TARGET_X86)
129147
context.targetARM64 = (targetName == GetTargetArmArch())
130148
context.targetUniversal = (targetName == TARGET_UNIVERSAL)
149+
context.targetIos = (targetName == TARGET_IOS)
131150
if context.targetUniversal and not SupportsMacOSUniversalBinaries():
132-
self.targetUniversal = False
151+
context.targetUniversal = False
133152
raise ValueError(
134153
"Universal binaries only supported in macOS 11.0 and later.")
135154

@@ -150,26 +169,63 @@ def ExtractFilesRecursive(path, cond):
150169
files.append(os.path.join(r, file))
151170
return files
152171

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'])
172+
def _GetCodeSignStringFromTerminal():
173+
codeSignIDs = GetCommandOutput(['security', 'find-identity', '-vp', 'codesigning'])
174+
return codeSignIDs
158175

159-
codeSignID = "-"
176+
def GetCodeSignID():
160177
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"
178+
return os.environ.get('CODE_SIGN_ID')
179+
180+
codeSignIDs = _GetCodeSignStringFromTerminal()
181+
if not codeSignIDs:
182+
return "-"
183+
for codeSignID in codeSignIDs.splitlines():
184+
if "CSSMERR_TP_CERT_REVOKED" in codeSignID:
185+
continue
186+
if ")" not in codeSignID:
187+
continue
188+
codeSignID = codeSignID.split()[1]
189+
break
190+
else:
191+
raise RuntimeError("Could not find a valid codesigning ID")
192+
193+
return codeSignID or "-"
194+
195+
def GetCodeSignIDHash():
196+
codeSignIDs = _GetCodeSignStringFromTerminal()
197+
try:
198+
return re.findall(r'\(.*?\)', codeSignIDs)[0][1:-1]
199+
except:
200+
raise Exception("Unable to parse codesign ID hash")
201+
202+
def GetDevelopmentTeamID():
203+
if os.environ.get("DEVELOPMENT_TEAM"):
204+
return os.environ.get("DEVELOPMENT_TEAM")
205+
codesignID = GetCodeSignIDHash()
206+
207+
certs = subprocess.check_output(["security", "find-certificate", "-c", codesignID, "-p"])
208+
subject = GetCommandOutput(["openssl", "x509", "-subject"], input=certs)
209+
subject = subject.splitlines()[0]
210+
211+
# Extract the Organizational Unit (OU field) from the cert
212+
try:
213+
team = [elm for elm in subject.split(
214+
'/') if elm.startswith('OU')][0].split('=')[1]
215+
if team is not None and team != "":
216+
return team
217+
except Exception as ex:
218+
raise Exception("No development team found with exception " + ex)
219+
220+
def CodesignFiles(files):
221+
codeSignID = GetCodeSignID()
167222

168223
for f in files:
169224
subprocess.call(['codesign', '-f', '-s', '{codesignid}'
170-
.format(codesignid=codeSignID), f],
225+
.format(codesignid=codeSignID), f],
171226
stdout=devout, stderr=devout)
172227

228+
173229
def Codesign(install_path, verbose_output=False):
174230
if not MacOS():
175231
return False
@@ -217,3 +273,12 @@ def CreateUniversalBinaries(context, libNames, x86Dir, armDir):
217273
instDir=context.instDir, libName=targetName),
218274
outputName)
219275
return lipoCommands
276+
277+
def ConfigureCMakeExtraArgs(context, args:List[str]) -> List[str]:
278+
system_name = None
279+
if context.buildTarget == TARGET_IOS:
280+
system_name = "iOS"
281+
282+
if system_name:
283+
args.append(f"-DCMAKE_SYSTEM_NAME={system_name}")
284+
return args

0 commit comments

Comments
 (0)