Skip to content
Open
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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,23 @@ Or for visionOS:
```
> python OpenUSD/build_scripts/build_usd.py --build-target visionOS --build-monolithic /path/to/my_usd_install_dir
```
###### Framework Builds (Experimental)

Builds for Apple platforms may optionally build as a framework using the `--build-apple-framework` flag.

**NOTE:** This feature is experimental and may change how it functions in future OpenUSD versions.

- Framework builds are enabled by default for iOS and visionOS build targets. It can optionally be enabled for macOS.
- Framework builds require monolithic builds.
- Building a universal macOS framework is currently not supported. Please generate the arches separately and `lipo`
them together after.

To add the Framework to your application, add `OpenUSD.framework` to your Xcode project.
It is recommended to set it to `Embed and Sign`.

To setup headers, configure the Xcode `SYSTEM_HEADER_SEARCH_PATHS` to add the path to your headers. e.g
`$(SRCROOT)/OpenUSD.framework/Headers` if the framework exists in your projects root.


##### Windows:

Expand Down
38 changes: 34 additions & 4 deletions build_scripts/build_usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,9 @@ def _RunBuild(arch):
if MacOSTargetEmbedded(context):
env["SDKROOT"] = apple_utils.GetSDKRoot(context)
buildArgs.append(f' compiler=clang arch=arm64 extra_inc=big_iron.inc target={context.buildTarget.lower()}')
if context.buildAppleFramework:
# Force build of static libs as well
buildArgs.append(f" extra_inc=big_iron.inc ")
makeTBBCmd = 'make -j{procs} arch={arch} {buildArgs}'.format(
arch=arch, procs=context.numJobs,
buildArgs=" ".join(buildArgs))
Expand Down Expand Up @@ -1547,9 +1550,7 @@ def InstallDraco(context, force, buildArgs):

def InstallMaterialX(context, force, buildArgs):
with CurrentWorkingDirectory(DownloadURL(MATERIALX_URL, context, force)):
cmakeOptions = ['-DMATERIALX_BUILD_SHARED_LIBS=ON',
'-DMATERIALX_BUILD_TESTS=OFF'
]
cmakeOptions = ['-DMATERIALX_BUILD_TESTS=OFF']

if MacOSTargetEmbedded(context):
# The materialXShaderGen in hdSt assumes the GLSL shadergen is
Expand All @@ -1569,6 +1570,10 @@ def InstallMaterialX(context, force, buildArgs):
' add_subdirectory(source/MaterialXRenderGlsl)\n' +
' endif()')
], multiLineMatches=True)
if MacOS() and context.buildAppleFramework:
cmakeOptions.extend(["-DMATERIALX_BUILD_SHARED_LIBS=OFF"])
else:
cmakeOptions.extend(["-DMATERIALX_BUILD_SHARED_LIBS=ON"])

cmakeOptions += buildArgs
RunCMake(context, force, cmakeOptions)
Expand Down Expand Up @@ -1840,6 +1845,8 @@ def InstallUSD(context, force, buildArgs):
if Windows():
# Increase the precompiled header buffer limit.
extraArgs.append('-DCMAKE_CXX_FLAGS="/Zm150"')
if MacOS():
extraArgs.append(f"-DPXR_BUILD_APPLE_FRAMEWORK={'ON' if context.buildAppleFramework else 'OFF'}")

# Make sure to use boost installed by the build script and not any
# system installed boost
Expand Down Expand Up @@ -1967,6 +1974,12 @@ def InstallUSD(context, force, buildArgs):
help=("Build target for macOS cross compilation. "
"(default: {})".format(
apple_utils.GetBuildTargetDefault())))
subgroup = group.add_mutually_exclusive_group()
subgroup.add_argument("--build-apple-framework", dest="build_apple_framework", action="store_true",
help="Build USD as an Apple Framework (Default if using embedded platforms)")
subgroup.add_argument("--no-build-apple-framework", dest="no_build_apple_framework", action="store_true",
help="Do not build USD as an Apple Framework (Default if macOS)")

if apple_utils.IsHostArm():
# Intel Homebrew stores packages in /usr/local which unfortunately can
# be where a lot of other things are too. So we only add this flag on arm macs.
Expand Down Expand Up @@ -2315,6 +2328,12 @@ def __init__(self, args):
else False)
if apple_utils.IsHostArm() and args.ignore_homebrew:
self.ignorePaths.append("/opt/homebrew")

self.buildAppleFramework = ((args.build_apple_framework or MacOSTargetEmbedded(self))
and not args.no_build_apple_framework)
if self.buildAppleFramework:
self.buildShared = False
self.buildMonolithic = True
else:
self.buildTarget = ""

Expand All @@ -2327,7 +2346,7 @@ def __init__(self, args):
self.forceBuild = [dep.lower() for dep in args.force_build]

# Some components are disabled for embedded build targets
embedded = MacOSTargetEmbedded(self)
embedded = (MacOS() and (MacOSTargetEmbedded(self) or self.buildAppleFramework))

# Optional components
self.buildTests = args.build_tests and not embedded
Expand Down Expand Up @@ -2669,6 +2688,11 @@ def _JoinVersion(v):
Use C++11 ABI {useCXX11ABI}
"""

if MacOS():
summaryMsg += """\
Framework Build {buildAppleFramework}
""".format(buildAppleFramework=("On" if context.buildAppleFramework else "Off"))

summaryMsg += """\
Variant {buildVariant}
Target {buildTarget}
Expand Down Expand Up @@ -2866,3 +2890,9 @@ def FormatBuildArguments(buildArgs):
if context.buildPrman:
Print("See documentation at http://openusd.org/docs/RenderMan-USD-Imaging-Plugin.html "
"for setting up the RenderMan plugin.\n")

if MacOS() and context.buildAppleFramework:
Print("""
Add the following framework to your Xcode Project, and add the headers folder within to your search path:
OpenUSD.framework
""")
9 changes: 9 additions & 0 deletions cmake/defaults/CXXDefaults.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,12 @@ if (PXR_PREFER_SAFETY_OVER_SPEED)
else()
set(PXR_PREFER_SAFETY_OVER_SPEED "0")
endif()

# Set that Apple Framework is being build
if (PXR_BUILD_APPLE_FRAMEWORK)
_add_define("PXR_BUILD_APPLE_FRAMEWORK")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @dgovil - I'm curious what the motivation is for this. It's currently not used by anything so is this ok to remove?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think it can be removed. It was vestigial from when I spilt up the PR

endif()

if(NOT PXR_EXTRA_BINARY_RELATIVE_RESOURCES STREQUAL "")
_add_define("PXR_EXTRA_BINARY_RELATIVE_RESOURCES=${PXR_EXTRA_BINARY_RELATIVE_RESOURCES}")
endif()
28 changes: 28 additions & 0 deletions cmake/defaults/Options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ if(APPLE)
set(PXR_ENABLE_OPENVDB_SUPPORT OFF)
endif()
endif ()

option(PXR_BUILD_APPLE_FRAMEWORK "Builds an Apple Framework." ${PXR_APPLE_EMBEDDED})
set(PXR_APPLE_FRAMEWORK_NAME "OpenUSD" CACHE STRING "Name to provide Apple Framework build")
set(PXR_APPLE_IDENTIFIER_DOMAIN "org.openusd" CACHE STRING "Name to provide Apple Framework build")
if (${PXR_BUILD_APPLE_FRAMEWORK})
if(${PXR_BUILD_USD_TOOLS})
MESSAGE(STATUS "Setting PXR_BUILD_USD_TOOLS=OFF because PXR_BUILD_APPLE_FRAMEWORK is enabled.")
endif()
set(PXR_BUILD_USD_TOOLS OFF)
if(${PXR_ENABLE_PYTHON_SUPPORT})
MESSAGE(STATUS "Setting PXR_ENABLE_PYTHON_SUPPORT=OFF because PXR_BUILD_APPLE_FRAMEWORK is enabled.")
endif ()
set(PXR_ENABLE_PYTHON_SUPPORT OFF)
endif()
endif()


Expand Down Expand Up @@ -159,7 +173,21 @@ set(PXR_EXTRA_PLUGINS ""
CACHE
INTERNAL
"Aggregation of extra plugin directories containing a plugInfo.json.")
set(PXR_EXTRA_BINARY_RELATIVE_RESOURCES ""
CACHE
STRING
"An optional resources folder relative to the binary to look for resources.")

if (${PXR_BUILD_APPLE_FRAMEWORK})
MESSAGE(STATUS "Framework build requires monolithic builds.")
set(PXR_BUILD_MONOLITHIC ON)
set(BUILD_SHARED_LIBS OFF)
if(PXR_APPLE_EMBEDDED)
set(PXR_EXTRA_BINARY_RELATIVE_RESOURCES "Assets")
else()
set(PXR_EXTRA_BINARY_RELATIVE_RESOURCES "Resources")
endif()
endif ()
# Resolve options that depend on one another so that subsequent .cmake scripts
# all have the final value for these options.
if (${PXR_BUILD_USD_IMAGING} AND NOT ${PXR_BUILD_IMAGING})
Expand Down
35 changes: 35 additions & 0 deletions cmake/macros/Private.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,11 @@ function(_pxr_add_rpath rpathRef target)
endfunction()

function(_pxr_install_rpath rpathRef NAME)
if (PXR_BUILD_APPLE_FRAMEWORK)
# Apple Frameworks already fix the install path at the end
# so this maks things faster and reduces duplication errors
return()
endif()
# Get and remove the origin.
list(GET ${rpathRef} 0 origin)
set(rpath ${${rpathRef}})
Expand Down Expand Up @@ -1538,3 +1543,33 @@ function(_pxr_library NAME)
endif()
endif()
endfunction() # _pxr_library

function(pxr_create_apple_framework)
# This function is used to create a framework build after the primary build is complete
# We could optionally have used the FRAMEWORK CMAKE Property (https://cmake.org/cmake/help/latest/prop_tgt/FRAMEWORK.html)
# However, the changes to make it work with the OpenUSD install process would have been significantly more
# invasive to orchestrate all the post-install steps that USD does.
# In the future, we can work towards making this

# CMake can have a lot of different boolean representations,
# that need to be narrowed down to a constant form for zsh
if (PXR_APPLE_EMBEDDED)
set(EMBEDDED_BUILD "true")
else()
set(EMBEDDED_BUILD "false")
endif()

_get_library_prefix(LIB_PREFIX)
if(TARGET usd_ms)
set(FRAMEWORK_ROOT_LIBRARY_NAME "${LIB_PREFIX}usd_ms.dylib")
else()
set(FRAMEWORK_ROOT_LIBRARY_NAME "${LIB_PREFIX}usd.dylib")
endif()

# Install the Info.plist and shell script
configure_file(cmake/resources/Info.plist.in "${PROJECT_BINARY_DIR}/Info.plist" @ONLY)
configure_file(cmake/resources/AppleFrameworkBuild.zsh.in "${PROJECT_BINARY_DIR}/AppleFrameworkBuild.zsh" @ONLY)

# Run the shell script for the primary configuration
install(CODE "execute_process(COMMAND zsh ${PROJECT_BINARY_DIR}/AppleFrameworkBuild.zsh )")
endfunction() # pxr_create_apple_framework
5 changes: 5 additions & 0 deletions cmake/macros/Public.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,11 @@ function(pxr_toplevel_epilogue)
# Setup the plugins in the top epilogue to ensure that everybody has had a
# chance to update PXR_EXTRA_PLUGINS with their plugin paths.
pxr_setup_plugins()

if (PXR_BUILD_APPLE_FRAMEWORK)
pxr_create_apple_framework()
endif ()

endfunction() # pxr_toplevel_epilogue

function(pxr_monolithic_epilogue)
Expand Down
6 changes: 5 additions & 1 deletion cmake/modules/FindOpenSubdiv.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,13 @@ endif()
SET(_opensubdiv_LIBRARIES)
FOREACH(COMPONENT ${_opensubdiv_FIND_COMPONENTS})
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
set(_lib_name ${COMPONENT})
if (APPLE AND PXR_BUILD_APPLE_FRAMEWORK)
set(_lib_name lib${COMPONENT}.a)
endif ()
FIND_LIBRARY(OPENSUBDIV_${UPPERCOMPONENT}_LIBRARY
NAMES
${COMPONENT}
${_lib_name}
HINTS
${_opensubdiv_SEARCH_DIRS}
PATH_SUFFIXES
Expand Down
13 changes: 11 additions & 2 deletions cmake/modules/FindTBB.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,22 @@ if(NOT TBB_FOUND)
set(_lib_name ${_comp})
endif()

set(_lib_names_release ${_lib_name})
set(_lib_names_debug ${_lib_name}_debug)

if (APPLE AND PXR_BUILD_APPLE_FRAMEWORK)
# When building a monolithic framework, it's best to take the static lib
set(_lib_names_release lib${_lib_name}.a)
set(_lib_names_debug lib${_lib_name}_debug.a)
endif ()

# Search for the libraries
find_library(TBB_${_comp}_LIBRARY_RELEASE ${_lib_name}
find_library(TBB_${_comp}_LIBRARY_RELEASE NAMES ${_lib_names_release}
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH
PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX})

find_library(TBB_${_comp}_LIBRARY_DEBUG ${_lib_name}_debug
find_library(TBB_${_comp}_LIBRARY_DEBUG NAMES ${_lib_names_debug}
HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR}
PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH
PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX})
Expand Down
87 changes: 87 additions & 0 deletions cmake/resources/AppleFrameworkBuild.zsh.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/bin/zsh

# Creates an Apple framework for the given platform type
# documentation: https://developer.apple.com/documentation/bundleresources/placing_content_in_a_bundle
# https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
# We use this instead of setting the FRAMEWORK property on the monolithic target to reduce how invasive a change this might be.
# See pxr_create_apple_framework in Public.cmake for more details
echo "⌛️ Creating @PXR_APPLE_FRAMEWORK_NAME@ ..."

# Variables are substituted by CMake
CMAKE_INSTALL_PREFIX="@CMAKE_INSTALL_PREFIX@"
PROJECT_BINARY_DIR="@PROJECT_BINARY_DIR@"

FRAMEWORK_NAME="@PXR_APPLE_FRAMEWORK_NAME@"
FRAMEWORK_DIR="${CMAKE_INSTALL_PREFIX}/frameworks/${FRAMEWORK_NAME}.framework"
FRAMEWORK_LIBRARIES_DIR="${FRAMEWORK_DIR}/Libraries"
FRAMEWORK_ROOT_LIBRARY_NAME="@FRAMEWORK_ROOT_LIBRARY_NAME@"
EMBEDDED_BUILD=@EMBEDDED_BUILD@
APPLY_HEADER_PREFIX=@APPLY_HEADER_PREFIX@
FRAMEWORK_RESOURCES_DIR="${FRAMEWORK_DIR}"
MATERIALX_SOURCE_LIBRARIES="${CMAKE_INSTALL_PREFIX}/libraries/"
BUNDLE_IDENTIFIER="@PXR_APPLE_IDENTIFIER_DOMAIN@.@PXR_APPLE_FRAMEWORK_NAME@"
CODESIGN_ID="@CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY@"
OLD_RC_PATH="${CMAKE_INSTALL_PREFIX}/lib"


# Remove the existing directory if it exists
if [ -d ${FRAMEWORK_DIR} ]; then
echo "Removing existing framework";
rm -Rf ${FRAMEWORK_DIR};
fi

# Create the parent directory
echo "Creating Framework Directory: ${FRAMEWORK_DIR}"
mkdir -p ${FRAMEWORK_DIR}

if [ "$EMBEDDED_BUILD" = true ];then
FRAMEWORK_RESOURCES_DIR="${FRAMEWORK_DIR}/Assets"
FRAMEWORK_PLIST_LOCATION="${FRAMEWORK_DIR}/Info.plist"
FRAMEWORK_HEADERS_DIR="${FRAMEWORK_DIR}/Headers"
FRAMEWORK_LIB_PATH=""${FRAMEWORK_DIR}/${FRAMEWORK_NAME}""
FRAMEWORK_LINKER_PATH="@rpath/Frameworks/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
else
FRAMEWORK_RESOURCES_DIR="${FRAMEWORK_DIR}/Versions/A/Resources/"
FRAMEWORK_PLIST_LOCATION="${FRAMEWORK_DIR}/Versions/A/Resources/Info.plist"
FRAMEWORK_HEADERS_DIR="${FRAMEWORK_DIR}/Versions/A/Headers"
FRAMEWORK_LIB_PATH="${FRAMEWORK_DIR}/Versions/A/${FRAMEWORK_NAME}"
FRAMEWORK_LINKER_PATH="@rpath/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}"
fi

echo "Creating Resources Root: ${FRAMEWORK_RESOURCES_DIR}"
mkdir -p ${FRAMEWORK_RESOURCES_DIR}

echo "Creating Headers Root: ${FRAMEWORK_HEADERS_DIR}"
mkdir -p ${FRAMEWORK_HEADERS_DIR}

# Copy the plist over
echo "Copying files into ${FRAMEWORK_DIR}"
ditto "${PROJECT_BINARY_DIR}/Info.plist" "${FRAMEWORK_PLIST_LOCATION}"


# Copy the MaterialX libraries if they exist
if [ -d "${MATERIALX_SOURCE_LIBRARIES}" ]; then
ditto ${MATERIALX_SOURCE_LIBRARIES} "${FRAMEWORK_RESOURCES_DIR}/libraries/"
fi


# Copy the primary directories over
ditto "${CMAKE_INSTALL_PREFIX}/include/" ${FRAMEWORK_HEADERS_DIR}
ditto "${CMAKE_INSTALL_PREFIX}/plugin/usd/" "${FRAMEWORK_RESOURCES_DIR}/usd"
ditto "${CMAKE_INSTALL_PREFIX}/lib/usd/" "${FRAMEWORK_RESOURCES_DIR}/usd"

cp "${CMAKE_INSTALL_PREFIX}/lib/${FRAMEWORK_ROOT_LIBRARY_NAME}" "${FRAMEWORK_LIB_PATH}"

# Setup symlinks
if [ "$EMBEDDED_BUILD" = false ];then
(cd "${FRAMEWORK_DIR}/Versions" && ln -s "A" "Current")
(cd ${FRAMEWORK_DIR} && ln -s "Versions/Current/Resources" "Resources")
(cd ${FRAMEWORK_DIR} && ln -s "Versions/Current/Headers" "Headers")
(cd ${FRAMEWORK_DIR} && ln -s "Versions/Current/${FRAMEWORK_NAME}" ${FRAMEWORK_NAME})
fi

# Fix the linkage on the primary dylib
install_name_tool -id "${FRAMEWORK_LINKER_PATH}" "${FRAMEWORK_DIR}/${FRAMEWORK_NAME}"
install_name_tool -change "@rpath/libusd_ms.dylib" "${FRAMEWORK_LINKER_PATH}" "${FRAMEWORK_DIR}/${FRAMEWORK_NAME}"

echo "✅ Finished creating framework at ${FRAMEWORK_DIR}"
24 changes: 24 additions & 0 deletions cmake/resources/Info.plist.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>@PXR_APPLE_FRAMEWORK_NAME@</string>
<key>CFBundleIdentifier</key>
<string>@PXR_APPLE_IDENTIFIER_DOMAIN@.@PXR_APPLE_FRAMEWORK_NAME@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>@PXR_APPLE_FRAMEWORK_NAME@</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>@PXR_MAJOR_VERSION@.@PXR_MINOR_VERSION@.@PXR_PATCH_VERSION@</string>
<key>CFBundleVersion</key>
<string>@PXR_VERSION@</string>
<key>CSResourcesFileMapped</key>
<true />
</dict>
</plist>
Loading
Loading