Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple Silicon Support #1875

Merged
merged 1 commit into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions build_scripts/apple_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/python
import sys
import locale
import os
import shlex
import subprocess

def GetLocale():
return sys.stdout.encoding or locale.getdefaultlocale()[1] or "UTF-8"

def GetCommandOutput(command):
"""Executes the specified command and returns output or None."""
try:
return subprocess.check_output(
shlex.split(command),
stderr=subprocess.STDOUT).decode(GetLocale(), 'replace').strip()
except subprocess.CalledProcessError:
pass
return None

def GetMacArmArch():
return os.environ.get('MACOS_ARM_ARCHITECTURE') or "arm64"

def GetMacArch():
macArch = GetCommandOutput('arch').strip()
if macArch == "i386" or macArch == "x86_64":
macArch = "x86_64"
else:
macArch = GetMacArmArch()
return macArch

devout = open(os.devnull, 'w')

def ExtractFilesRecursive(path, cond):
files = []
for r, d, f in os.walk(path):
for file in f:
if cond(os.path.join(r,file)):
files.append(os.path.join(r, file))
return files

def CodesignFiles(files):
SDKVersion = subprocess.check_output(['xcodebuild', '-version']).strip()[6:10]
codeSignIDs = subprocess.check_output(['security', 'find-identity', '-vp', 'codesigning'])

codeSignID = "-"
if os.environ.get('CODE_SIGN_ID'):
codeSignID = os.environ.get('CODE_SIGN_ID')
elif float(SDKVersion) >= 11.0 and codeSignIDs.find(b'Apple Development') != -1:
codeSignID = "Apple Development"
elif codeSignIDs.find(b'Mac Developer') != -1:
codeSignID = "Mac Developer"

for f in files:
subprocess.call(['codesign', '-f', '-s', '{codesignid}'
.format(codesignid=codeSignID), f],
stdout=devout, stderr=devout)

def Codesign(install_path, verbose_output=False):
if verbose_output:
global devout
devout = sys.stdout

files = ExtractFilesRecursive(install_path,
(lambda file: '.so' in file or '.dylib' in file))
CodesignFiles(files)
97 changes: 76 additions & 21 deletions build_scripts/build_usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import sysconfig
import tarfile
import zipfile
import apple_utils

if sys.version_info.major >= 3:
from urllib.request import urlopen
Expand Down Expand Up @@ -90,8 +91,6 @@ def Linux():
return platform.system() == "Linux"
def MacOS():
return platform.system() == "Darwin"
def Arm():
return platform.processor() == "arm"

def Python3():
return sys.version_info.major == 3
Expand Down Expand Up @@ -887,9 +886,10 @@ def InstallTBB_LinuxOrMacOS(context, force, buildArgs):
AppendCXX11ABIArg("CXXFLAGS", context, buildArgs)

# Ensure that the tbb build system picks the proper architecture.
if MacOS() and Arm():
buildArgs.append("arch=arm64")

if MacOS():
if apple_utils.GetMacArch() != "x86_64":
buildArgs.append("arch=arm64")

# TBB does not support out-of-source builds in a custom location.
Run('make -j{procs} {buildArgs}'
.format(procs=context.numJobs,
Expand Down Expand Up @@ -983,13 +983,12 @@ def InstallTIFF(context, force, buildArgs):
PNG_URL = "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.29.tar.gz"

def InstallPNG(context, force, buildArgs):
macArgs = []
if MacOS() and Arm():
# ensure libpng's build doesn't erroneously activate inappropriate
# Neon extensions
macArgs = ["-DPNG_HARDWARE_OPTIMIZATIONS=OFF",
"-DPNG_ARM_NEON=off"] # case is significant
with CurrentWorkingDirectory(DownloadURL(PNG_URL, context, force)):
macArgs = []
if MacOS() and apple_utils.GetMacArch() != "x86_64":
# Ensure libpng's build doesn't erroneously activate inappropriate
# Neon extensions
macArgs = ["-DCMAKE_C_FLAGS=\"-DPNG_ARM_NEON_OPT=0\""]
RunCMake(context, force, buildArgs + macArgs)

PNG = Dependency("PNG", InstallPNG, "include/png.h")
Expand Down Expand Up @@ -1080,7 +1079,11 @@ def InstallPtex_LinuxOrMacOS(context, force, buildArgs):

def InstallBLOSC(context, force, buildArgs):
with CurrentWorkingDirectory(DownloadURL(BLOSC_URL, context, force)):
RunCMake(context, force, buildArgs)
macArgs = []
if MacOS() and apple_utils.GetMacArch() != "x86_64":
# Need to disable SSE for macOS ARM targets.
macArgs = ["-DDEACTIVATE_SSE2=ON"]
RunCMake(context, force, buildArgs + macArgs)

BLOSC = Dependency("Blosc", InstallBLOSC, "include/blosc.h")

Expand Down Expand Up @@ -1187,6 +1190,21 @@ def InstallOpenColorIO(context, force, buildArgs):
[("IMPORTED_LOCATION_RELEASE",
"IMPORTED_LOCATION_RELWITHDEBINFO")])

if MacOS():
arch = apple_utils.GetMacArch()

PatchFile("CMakeLists.txt",
[('CMAKE_ARGS ${TINYXML_CMAKE_ARGS}',
'CMAKE_ARGS ${TINYXML_CMAKE_ARGS}\n' +
' CMAKE_CACHE_ARGS -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH:BOOL=TRUE'
' -DCMAKE_OSX_ARCHITECTURES:STRING="{arch}"'.format(arch=arch)),
('CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS}',
'CMAKE_ARGS ${YAML_CPP_CMAKE_ARGS}\n' +
' CMAKE_CACHE_ARGS -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH:BOOL=TRUE'
' -DCMAKE_OSX_ARCHITECTURES:STRING="{arch}"'.format(arch=arch)),
('set(CMAKE_OSX_ARCHITECTURES x86_64 CACHE STRING',
'set(CMAKE_OSX_ARCHITECTURES "{arch}" CACHE STRING'.format(arch=arch))])

# The OCIO build treats all warnings as errors but several come up
# on various platforms, including:
# - On gcc6, v1.1.0 emits many -Wdeprecated-declaration warnings for
Expand All @@ -1204,6 +1222,16 @@ def InstallOpenColorIO(context, force, buildArgs):
pass
else:
extraArgs.append('-DCMAKE_CXX_FLAGS=-w')

if MacOS():
#if using version 2 of OCIO we patch a different config path as it resides elsewere
PatchFile("src/core/Config.cpp",
[("cacheidnocontext_ = cacheidnocontext_;",
"cacheidnocontext_ = rhs.cacheidnocontext_;")])

extraArgs.append('-DCMAKE_CXX_FLAGS="-Wno-unused-function -Wno-unused-const-variable -Wno-unused-private-field"')
if (apple_utils.GetMacArch() != "x86_64"):
extraArgs.append('-DOCIO_USE_SSE=OFF')

# Add on any user-specified extra arguments.
extraArgs += buildArgs
Expand Down Expand Up @@ -1304,16 +1332,26 @@ def GetPySideInstructions():
'If PySide is already installed, you may need to '
'update your PYTHONPATH to indicate where it is '
'located.')
else:
return ('PySide2 is not installed. If you have pip '
elif MacOS():
# PySide6 is required for Apple Silicon support, so is the default
# across all macOS hardware platforms.
return ('PySide6 is not installed. If you have pip '
'installed, run "pip install PySide6" '
'to install it, then re-run this script.\n'
'If PySide6 is already installed, you may need to '
'update your PYTHONPATH to indicate where it is '
'located.')
else:
return ('PySide2 or PySide6 are not installed. If you have pip '
'installed, run "pip install PySide2" '
'to install it, then re-run this script.\n'
'If PySide2 is already installed, you may need to '
'update your PYTHONPATH to indicate where it is '
'located.')


PYSIDE = PythonDependency("PySide", GetPySideInstructions,
moduleNames=["PySide", "PySide2"])
moduleNames=["PySide", "PySide2", "PySide6"])

############################################################
# HDF5
Expand All @@ -1336,6 +1374,10 @@ def InstallHDF5(context, force, buildArgs):

def InstallAlembic(context, force, buildArgs):
with CurrentWorkingDirectory(DownloadURL(ALEMBIC_URL, context, force)):
if MacOS():
PatchFile("CMakeLists.txt",
[("ADD_DEFINITIONS(-Wall -Werror -Wextra -Wno-unused-parameter)",
"ADD_DEFINITIONS(-Wall -Wextra -Wno-unused-parameter)")])
cmakeOptions = ['-DUSE_BINARIES=OFF', '-DUSE_TESTS=OFF']
if context.enableHDF5:
# HDF5 requires the H5_BUILT_AS_DYNAMIC_LIB macro be defined if
Expand Down Expand Up @@ -1389,10 +1431,10 @@ def InstallMaterialX(context, force, buildArgs):

############################################################
# Embree
# For MacOS we use version 3.7.0 to include a fix from Intel
# to build on Catalina.
# For MacOS we use version 3.13.3 to include a fix from Intel
# to build on Apple Silicon.
if MacOS():
EMBREE_URL = "https://github.com/embree/embree/archive/v3.7.0.tar.gz"
EMBREE_URL = "https://github.com/embree/embree/archive/v3.13.3.tar.gz"
else:
EMBREE_URL = "https://github.com/embree/embree/archive/v3.2.2.tar.gz"

Expand Down Expand Up @@ -1703,6 +1745,10 @@ def InstallUSD(context, force, buildArgs):
group.add_argument("--toolset", type=str,
help=("CMake toolset to use when building libraries with "
"cmake"))
if MacOS():
codesignDefault = False if apple_utils.GetMacArch() == "x64_64" else True
group.add_argument("--codesign", dest="macos_codesign", default=codesignDefault,
help=("Use codesigning for macOS builds (defaults to enabled on Apple Silicon)"))

if Linux():
group.add_argument("--use-cxx11-abi", type=int, choices=[0, 1],
Expand Down Expand Up @@ -1953,6 +1999,8 @@ def __init__(self, args):
self.useCXX11ABI = \
(args.use_cxx11_abi if hasattr(args, "use_cxx11_abi") else None)
self.safetyFirst = args.safety_first
self.macOSCodesign = \
(args.macos_codesign if hasattr(args, "macos_codesign") else False)

# Dependencies that are forced to be built
self.forceBuildAll = args.force_all
Expand Down Expand Up @@ -2160,22 +2208,24 @@ def _JoinVersion(v):
# The USD build will skip building usdview if pyside2-uic or pyside-uic is
# not found, so check for it here to avoid confusing users. This list of
# PySide executable names comes from cmake/modules/FindPySide.cmake
pyside6Uic = ["pyside6-uic", "uic"]
found_pyside6Uic = any([which(p) for p in pyside6Uic])
pyside2Uic = ["pyside2-uic", "python2-pyside2-uic", "pyside2-uic-2.7", "uic"]
found_pyside2Uic = any([which(p) for p in pyside2Uic])
pysideUic = ["pyside-uic", "python2-pyside-uic", "pyside-uic-2.7"]
found_pysideUic = any([which(p) for p in pysideUic])
if not given_pysideUic and not found_pyside2Uic and not found_pysideUic:
if not given_pysideUic and not found_pyside2Uic and not found_pysideUic and not found_pyside6Uic:
if Windows():
# Windows does not support PySide2 with Python2.7
PrintError("pyside-uic not found -- please install PySide and"
" adjust your PATH. (Note that this program may be named"
" {0} depending on your platform)"
.format(" or ".join(pysideUic)))
else:
PrintError("pyside2-uic not found -- please install PySide2 and"
PrintError("uic not found-- please install PySide2 or PySide6 and"
" adjust your PATH. (Note that this program may be"
" named {0} depending on your platform)"
.format(" or ".join(pyside2Uic)))
.format(" or ".join(set(pyside2Uic+pyside6Uic))))
sys.exit(1)

if JPEG in requiredDependencies:
Expand Down Expand Up @@ -2266,6 +2316,7 @@ def FormatBuildArguments(buildArgs):
else "Release w/ Debug Info" if context.buildRelWithDebug
else ""),
buildImaging=("On" if context.buildImaging else "Off"),
macOSCodesign=("On" if context.macOSCodesign else "Off"),
enablePtex=("On" if context.enablePtex else "Off"),
enableOpenVDB=("On" if context.enableOpenVDB else "Off"),
buildOIIO=("On" if context.buildOIIO else "Off"),
Expand Down Expand Up @@ -2345,6 +2396,10 @@ def FormatBuildArguments(buildArgs):
os.path.join(context.instDir, "lib")
])

if MacOS():
if context.macOSCodesign:
apple_utils.Codesign(context.usdInstDir, verbosity > 1)

Print("""
Success! To use USD, please ensure that you have:""")

Expand Down
22 changes: 18 additions & 4 deletions cmake/modules/FindPySide.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,27 @@ if (NOT PYTHON_EXECUTABLE)
return()
endif()

# Prefer PySide2 over PySide
# Prefer PySide6 over PySide2 and PySide
# Note: Windows does not support PySide2 with Python2.7
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" "-c" "import PySide2"
COMMAND "${PYTHON_EXECUTABLE}" "-c" "import PySide6"
RESULT_VARIABLE pySideImportResult
)
if (pySideImportResult EQUAL 0)
set(pySideImportResult "PySide2")
set(pySideUIC pyside2-uic python2-pyside2-uic pyside2-uic-2.7 uic)
set(pySideImportResult "PySide6")
set(pySideUIC pyside6-uic python3-pyside6-uic uic)
endif()

# PySide6 not found
if (pySideImportResult EQUAL 1)
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" "-c" "import PySide2"
RESULT_VARIABLE pySideImportResult
)
if (pySideImportResult EQUAL 0)
set(pySideImportResult "PySide2")
set(pySideUIC pyside2-uic python2-pyside2-uic pyside2-uic-2.7 uic)
endif()
endif()

# PySide2 not found OR PYSIDE explicitly requested
Expand Down Expand Up @@ -66,6 +78,8 @@ if (pySideImportResult)
else()
if (PYSIDE_USE_PYSIDE)
message(STATUS "Did not find PySide with ${PYTHON_EXECUTABLE}")
elseif (PYSIDE_USE_PYSIDE6)
message(STATUS "Did not find PySide6 with ${PYTHON_EXECUTABLE}")
else()
message(STATUS "Did not find PySide2 with ${PYTHON_EXECUTABLE}")
endif()
Expand Down
Loading