Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.p4*
.DS_Store
.AppleDouble
USD_emscripten/
.vscode/

11 changes: 10 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12)

project(usd)

if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT PXR_ENABLE_JS_SUPPORT)
if (WIN32)
message(FATAL_ERROR "Compiler does not support 64-bit builds. "
"If you are using Visual Studio, make sure you are in the "
Expand Down Expand Up @@ -37,6 +37,15 @@ include(CXXDefaults)
add_definitions(${_PXR_CXX_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${_PXR_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")

if(PXR_ENABLE_JS_SUPPORT)
# Add EMSCRIPTEN specific compiler flags (is this the right place)?
set(EMSCRIPTEN_COMPILE_FLAGS "-s ALLOW_MEMORY_GROWTH=1 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -s MODULARIZE=1 -s EXPORT_NAME='getUsdModule' -s 'EXTRA_EXPORTED_RUNTIME_METHODS=[\"FS\"]' -s FORCE_FILESYSTEM=1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EMSCRIPTEN_COMPILE_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EMSCRIPTEN_COMPILE_FLAGS}")

message("EMSCRIPTEN Flags enabled")
endif()

include(Public)

pxr_toplevel_prologue()
Expand Down
32 changes: 32 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
FROM ubuntu:20.04
SHELL ["/bin/bash", "-c"]

ARG CMAKE_VERSION=3.20.3
ARG EMSCRIPTEN_VERSION=2.0.24

RUN apt-get -y update && apt-get install -y\
python-setuptools \
libglew-dev \
libxrandr-dev \
libxcursor-dev \
libxinerama-dev \
libxi-dev \
python3-pip \
git \
curl

RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs libglib2.0-0

RUN pip install --upgrade pip
RUN pip install PySide2 PyOpenGL Jinja2

# Updating cmake version
RUN apt remove cmake
RUN pip install cmake==${CMAKE_VERSION}

RUN mkdir -p tmp && cd tmp && git clone --recursive https://github.com/emscripten-core/emsdk
RUN cd /tmp/emsdk && ./emsdk install ${EMSCRIPTEN_VERSION}
RUN cd /tmp/emsdk && ./emsdk activate ${EMSCRIPTEN_VERSION} --permanent

COPY . /src/
RUN source /tmp/emsdk/emsdk_env.sh && cd /src && python3 ./build_scripts/build_usd.py --emscripten USD_emscripten
107 changes: 101 additions & 6 deletions build_scripts/build_usd.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ def RunCMake(context, force, extraArgs = None):
AppendCXX11ABIArg("-DCMAKE_CXX_FLAGS", context, extraArgs)

with CurrentWorkingDirectory(buildDir):
Run('cmake '
Run(('emcmake ' if context.emscripten else '') +
'cmake '
'-DCMAKE_INSTALL_PREFIX="{instDir}" '
'-DCMAKE_PREFIX_PATH="{depsInstDir}" '
'-DCMAKE_BUILD_TYPE={config} '
Expand All @@ -437,7 +438,8 @@ def RunCMake(context, force, extraArgs = None):
generator=(generator or ""),
toolset=(toolset or ""),
extraArgs=(" ".join(extraArgs) if extraArgs else "")))
Run("cmake --build . --config {config} --target install -- {multiproc}"
Run(('emmake ' if context.emscripten else '') +
"cmake --build . --config {config} --target install -- {multiproc}"
.format(config=config,
multiproc=FormatMultiProcs(context.numJobs, generator)))

Expand Down Expand Up @@ -594,6 +596,8 @@ def DownloadURL(url, context, force, extractDir = None,
members = (m for m in archive.getnames()
if not any((fnmatch.fnmatch(m, p)
for p in dontExtract)))
elif filename.endswith('.js'):
return os.path.abspath(filename)
else:
raise RuntimeError("unrecognized archive file type")

Expand Down Expand Up @@ -863,8 +867,13 @@ def InstallBoost(context, force, buildArgs):
else:
TBB_URL = "https://github.com/oneapi-src/oneTBB/archive/2018_U6.tar.gz"

# Note: this refers to a fork of tbb for wasm. Is this maintained?
TBB_EMSCRIPTEN_URL = "https://github.com/sdunkel/wasmtbb/archive/master.zip"

def InstallTBB(context, force, buildArgs):
if Windows():
if context.emscripten:
InstallTBB_Emscripten(context, force, buildArgs)
elif Windows():
InstallTBB_Windows(context, force, buildArgs)
elif Linux() or MacOS():
InstallTBB_LinuxOrMacOS(context, force, buildArgs)
Expand Down Expand Up @@ -912,6 +921,29 @@ def InstallTBB_LinuxOrMacOS(context, force, buildArgs):
CopyDirectory(context, "include/serial", "include/serial")
CopyDirectory(context, "include/tbb", "include/tbb")

def InstallTBB_Emscripten(context, force, buildArgs):

with CurrentWorkingDirectory(DownloadURL(TBB_EMSCRIPTEN_URL, context, force)):
# By default no config for macos is avaiable, but the one for linux
# seems to work fine
if MacOS():
shutil.copy('build/linux.emscripten.inc', 'build/macos.emscripten.inc')

# TBB does not support out-of-source builds in a custom location.
Run('emmake make -j{procs} extra_inc=big_iron.inc tbb {buildArgs}'
.format(procs=context.numJobs,
buildArgs=" ".join(buildArgs)))

# Install both release and debug builds. USD requires the debug
# libraries when building in debug mode, and installing both
# makes it easier for users to install dependencies in some
# location that can be shared by both release and debug USD
# builds. Plus, the TBB build system builds both versions anyway.
CopyFiles(context, "build/*_release/libtbb*.*", "lib")
CopyFiles(context, "build/*_debug/libtbb*.*", "lib")
CopyDirectory(context, "include/serial", "include/serial")
CopyDirectory(context, "include/tbb", "include/tbb")

TBB = Dependency("TBB", InstallTBB, "include/tbb/tbb.h")

############################################################
Expand Down Expand Up @@ -1209,6 +1241,12 @@ def InstallOpenSubdiv(context, force, buildArgs):
'-DNO_GLEW=ON',
'-DNO_GLFW=ON',
]
if context.emscripten:
extraArgs.append('-DBUILD_SHARED_LIB=OFF')
extraArgs.append('-DCMAKE_CXX_FLAGS="-s USE_PTHREADS=1"')
extraArgs.append('-DCMAKE_C_FLAGS="-s USE_PTHREADS=1"')
extraArgs.append('-DNO_OPENGL=ON')
extraArgs.append('-DNO_METAL=ON')

# If Ptex support is disabled in USD, disable support in OpenSubdiv
# as well. This ensures OSD doesn't accidentally pick up a Ptex
Expand Down Expand Up @@ -1239,7 +1277,7 @@ def InstallOpenSubdiv(context, force, buildArgs):
# just 1 job for now. See:
# https://github.com/PixarAnimationStudios/OpenSubdiv/issues/1194
oldNumJobs = context.numJobs
if MacOS():
if MacOS() or context.emscripten:
context.numJobs = 1

try:
Expand Down Expand Up @@ -1560,6 +1598,21 @@ def InstallUSD(context, force, buildArgs):
extraArgs.append('-DBoost_NO_SYSTEM_PATHS=True')
extraArgs += buildArgs

if context.emscripten:
extraArgs.append('-DPXR_ENABLE_JS_SUPPORT=ON')
# For some reason we have to manually specify path to boost
extraArgs.append('-DBoost_INCLUDE_DIR='+os.path.join(context.usdInstDir, "include"))

extraArgs.append('-DTBB_INCLUDE_DIRS=' + os.path.join(context.usdInstDir, 'include'))
extraArgs.append('-DTBB_tbb_LIBRARY_DEBUG=' + os.path.join(context.usdInstDir, 'lib/libtbb_debug.a'))
extraArgs.append('-DTBB_tbb_LIBRARY_RELEASE=' + os.path.join(context.usdInstDir, 'lib/libtbb.a'))

extraArgs.append('-DOPENSUBDIV_INCLUDE_DIR=' + os.path.join(context.usdInstDir, 'include'))
extraArgs.append('-DOPENSUBDIV_OSDCPU_LIBRARY=' + os.path.join(context.usdInstDir, 'lib/libosdCPU.a'))

extraArgs.append('-DPXR_ENABLE_GL_SUPPORT=OFF')
extraArgs.append('-DBUILD_SHARED_LIBS=OFF')

RunCMake(context, force, extraArgs)

USD = Dependency("USD", InstallUSD, "include/pxr/pxr.h")
Expand Down Expand Up @@ -1683,6 +1736,9 @@ def InstallUSD(context, force, buildArgs):
group.add_argument("--toolset", type=str,
help=("CMake toolset to use when building libraries with "
"cmake"))
subgroup = group.add_mutually_exclusive_group()
subgroup.add_argument("--emscripten", dest="emscripten", action="store_const", const='EMSCRIPTEN',
help="Build for emscripten")

if Linux():
group.add_argument("--use-cxx11-abi", type=int, choices=[0, 1],
Expand Down Expand Up @@ -1892,6 +1948,7 @@ def __init__(self, args):
# CMake generator and toolset
self.cmakeGenerator = args.generator
self.cmakeToolset = args.toolset
self.emscripten = args.emscripten

# Number of jobs
self.numJobs = args.jobs
Expand Down Expand Up @@ -2014,9 +2071,45 @@ def ForceBuildDependency(self, dep):
paths = os.environ.get('PYTHONPATH', '').split(os.pathsep) + extraPythonPaths
os.environ['PYTHONPATH'] = os.pathsep.join(paths)

# Disable incompatible options if emscripten is used
if context.emscripten:
disabled = []
if context.buildPython:
context.buildPython = False
disabled.append('Python')

if context.buildImaging:
context.buildImaging = NO_IMAGING
disabled.append('imaging')

if context.buildUsdImaging:
context.buildUsdImaging = NO_IMAGING
disabled.append('usdImaging')

if context.buildExamples:
context.buildExamples = False
disabled.append('examples')

if context.buildTutorials:
context.buildTutorials = False
disabled.append('tutorials')

if context.buildTools:
context.buildTools = False
disabled.append('tools')

if context.buildUsdview:
context.buildUsdview = False
disabled.append('usdview')

if len(disabled) > 0:
print("The following components were disabled because they are not compatible with emscripten: " + ", ".join(disabled))

# Determine list of dependencies that are required based on options
# user has selected.
requiredDependencies = [ZLIB, BOOST, TBB]
requiredDependencies = [BOOST, TBB]
if not context.emscripten:
requiredDependencies += [ZLIB]

if context.buildAlembic:
if context.enableHDF5:
Expand Down Expand Up @@ -2054,7 +2147,7 @@ def ForceBuildDependency(self, dep):
# our own. This avoids potential issues where a host application
# loads an older version of zlib than the one we'd build and link
# our libraries against.
if Linux():
if Linux() and ZLIB in requiredDependencies:
requiredDependencies.remove(ZLIB)

# Error out if user is building monolithic library on windows with draco plugin
Expand Down Expand Up @@ -2173,6 +2266,7 @@ def _JoinVersion(v):
Build directory {buildDir}
CMake generator {cmakeGenerator}
CMake toolset {cmakeToolset}
Emscripten {emscripten}
Downloader {downloader}

Building {buildType}
Expand Down Expand Up @@ -2232,6 +2326,7 @@ def FormatBuildArguments(buildArgs):
else context.cmakeGenerator),
cmakeToolset=("Default" if not context.cmakeToolset
else context.cmakeToolset),
emscripten=("Enabled" if context.emscripten else "Disabled"),
downloader=(context.downloaderName),
dependencies=("None" if not dependenciesToBuild else
", ".join([d.name for d in dependenciesToBuild])),
Expand Down
8 changes: 8 additions & 0 deletions cmake/defaults/Options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ option(PXR_BUILD_PRMAN_PLUGIN "Build the PRMan imaging plugin" OFF)
option(PXR_ENABLE_MATERIALX_SUPPORT "Enable MaterialX support" OFF)
option(PXR_BUILD_DOCUMENTATION "Generate doxygen documentation" OFF)
option(PXR_ENABLE_PYTHON_SUPPORT "Enable Python based components for USD" ON)
option(PXR_ENABLE_JS_SUPPORT "Enable Javascript based components for USD" OFF)
option(PXR_USE_PYTHON_3 "Build Python bindings for Python 3" OFF)
option(PXR_USE_DEBUG_PYTHON "Build with debug python" OFF)
option(PXR_ENABLE_HDF5_SUPPORT "Enable HDF5 backend in the Alembic plugin for USD" ON)
Expand Down Expand Up @@ -186,3 +187,10 @@ if (${PXR_BUILD_DRACO_PLUGIN} AND ${PXR_BUILD_MONOLITHIC} AND WIN32)
message(FATAL_ERROR
"Draco plugin can not be enabled for monolithic builds on Windows")
endif()

# Error out if user is building with Emscripten and tests.
# This is currently not supported.
if (${PXR_ENABLE_JS_SUPPORT} AND ${PXR_BUILD_TESTS})
message(FATAL_ERROR
"Emscripten build can not be enabled together with tests")
endif()
9 changes: 9 additions & 0 deletions cmake/defaults/Packages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ else()
find_package(PythonInterp 2.7 REQUIRED)
endif()
endif()

# --Boost
if(NOT PXR_ENABLE_JS_SUPPORT)
find_package(Boost
COMPONENTS
program_options
REQUIRED
)
endif()
endif()

# --USD tools
Expand Down
14 changes: 14 additions & 0 deletions cmake/macros/Private.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,26 @@ function(_install_resource_files NAME pluginInstallPrefix pluginToLibraryPath)
_plugInfo_subst(${NAME} "${pluginToLibraryPath}" ${resourceFile})
endif()
set(resourceFile "${CMAKE_CURRENT_BINARY_DIR}/${resourceFile}")
set(EMSCRIPTEN_RESOURCE_FILE ${resourceFile})
else()
set(EMSCRIPTEN_RESOURCE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${resourceFile}")
endif()

if (PXR_ENABLE_JS_SUPPORT)
string(REGEX REPLACE "^lib\\/" "/" LOCAL_PATH "${resourcesPath}")

list(APPEND EMSCRIPTEN_RESOURCE_FILES "--embed-file ${EMSCRIPTEN_RESOURCE_FILE}@${LOCAL_PATH}/${dirPath}/${destFileName}")
endif()
install(
FILES ${resourceFile}
DESTINATION ${resourcesPath}/${dirPath}
RENAME ${destFileName}
)
endforeach()

if (PXR_ENABLE_JS_SUPPORT)
set_property(TARGET ${NAME} PROPERTY EMSCRIPTEN_RESOURCES ${EMSCRIPTEN_RESOURCE_FILES})
endif()
endfunction() # _install_resource_files

function(_install_pyside_ui_files LIBRARY_NAME)
Expand Down Expand Up @@ -854,6 +866,8 @@ function(_pxr_target_link_libraries NAME)
list(APPEND final ${lib})
elseif(CMAKE_COMPILER_IS_GNUCXX)
list(APPEND final -Wl,--whole-archive ${lib} -Wl,--no-whole-archive)
elseif(PXR_ENABLE_JS_SUPPORT)
list(APPEND final -Wl,--whole-archive ${lib} -Wl,--no-whole-archive)
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
list(APPEND final -Wl,-force_load ${lib})
else()
Expand Down
23 changes: 23 additions & 0 deletions cmake/macros/Public.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,11 @@ function(pxr_library NAME)
PYMODULE_CPPFILES
PYMODULE_FILES
PYSIDE_UI_FILES
JS_PUBLIC_CLASSES
JS_PRIVATE_CLASSES
JS_PUBLIC_HEADERS
JS_PRIVATE_HEADERS
JS_CPPFILES
)

cmake_parse_arguments(args
Expand Down Expand Up @@ -265,6 +270,24 @@ function(pxr_library NAME)
endif()
endif()

if(PXR_ENABLE_JS_SUPPORT)
if(args_JS_PUBLIC_CLASSES)
list(APPEND args_PUBLIC_CLASSES ${args_JS_PUBLIC_CLASSES})
endif()
if(args_JS_PUBLIC_HEADERS)
list(APPEND args_PUBLIC_HEADERS ${args_JS_PUBLIC_HEADERS})
endif()
if(args_JS_PRIVATE_CLASSES)
list(APPEND args_PRIVATE_CLASSES ${args_JS_PRIVATE_CLASSES})
endif()
if(args_JS_PRIVATE_HEADERS)
list(APPEND args_PRIVATE_HEADERS ${args_JS_PRIVATE_HEADERS})
endif()
if(args_JS_CPPFILES)
list(APPEND args_CPPFILES ${args_JS_CPPFILES})
endif()
endif()

# Collect libraries.
if(NOT args_TYPE STREQUAL "PLUGIN")
get_property(help CACHE PXR_ALL_LIBS PROPERTY HELPSTRING)
Expand Down
3 changes: 3 additions & 0 deletions extras/usd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ endif()
if (PXR_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if (PXR_ENABLE_JS_SUPPORT)
add_subdirectory(js_bindings)
endif()
Loading