Building OpenUSD

Tips for compiling on different architectures, and common pitfalls

Building OpenUSD

Compiling USD is not always necessary, if you can use a prebuilt option I'd recommend it. Historically building USD has been one of the most difficult parts of using it. It's gotten a lot better since the early days. I've occasionally managed to get it working on the first try, but I always assume building for a new platform will take somewhere between a few hours and a full day. Your mileage may vary.

When to Build

The good news is that it's pretty easy to get an already compiled version.

If you can use the USD libraries that come with your tools, that's a great place to find them. Blender, Houdini and Maya all ship with USD libraries now. You can also find pre-compiled binaries like the version NVIDIA provides. These will also usually include usdview and other tools.

Pixar Universal Scene Description (USD)
An open source 3D scene description for 3D content creation.

If you only need python support you can use the usd-core package on PyPI, get it with pip install usd-core.

This covers a lot of use cases. You might still want to build USD yourself though if, for instance:

  • There are no packages available for your platform
  • You want access to a specific USD version with specific plugins
  • You want to write new plugins for Schemas, Hydra, Asset Resolvers, etc.
  • You just want to tinker and have a lot of free time 🤓

Building with build_usd.py

If you've decided to build USD, this is the first thing to try. The script takes parameters with common configuration switches, like enabling python, imaging, alembic support, stuff like that. The build script will figure out what dependencies it needs, download source for them, and build compatible versions of the dependencies. The artifacts from those builds are then vendored into the USD build output, so that it has everything it needs to run.

See the documentation on github for all the details. The most basic usage looks like this, run from the root of the git repository.

python build_scripts/build_usd.py ../my-usd-build

That will generate a USD build that includes python support and usdview. The build output will go into the folder ../my-usd-build. I placed it in the parent directory so that it is outside the git managed USD source tree.

You can also do a "dry run" build with the -n flag or --dry_run. This will compute the dependencies and come up with a build plan, report that plan at the command line, and exit without doing anything.

Before building on my M1 Macbook I created the setup below, but on another platform you'd need to do the equivalent (get a C++ build toolchain, get CMake, install necessary python packages).

  1. Xcode tools installed
  2. CMake installed with homebrew
  3. pyside6, PyOpenGL and jinja2 installed in a python virtual env

The output of a dryrun looks like this:

❯ python build_scripts/build_usd.py -n ../my-usd-build

Building with settings:
  USD source directory          /Projects/github/rstelzleni/USD
  USD install directory         /Projects/github/rstelzleni/my-usd-build
  3rd-party source directory    /Projects/github/rstelzleni/my-usd-build/src
  3rd-party install directory   /Projects/github/rstelzleni/my-usd-build
  Build directory               /Projects/github/rstelzleni/my-usd-build/build
  CMake generator               Default
  CMake toolset                 Default
  Downloader                    curl

  Building                      Shared libraries
    Variant                     Release
    Target                      native
    Imaging                     On
      Ptex support:             Off
      OpenVDB support:          Off
      OpenImageIO support:      Off 
      OpenColorIO support:      Off 
      PRMan support:            Off
    UsdImaging                  On
      usdview:                  On
    Python support              On
      Python Debug:             Off
      Python docs:              Off
    Documentation               Off
    Tests                       Off
      Mayapy Tests:             Off
      AnimX Tests:              Off
    Examples                    On
    Tutorials                   On
    Tools                       On
    Alembic Plugin              Off
      HDF5 support:             Off
    Draco Plugin                Off
    MaterialX Plugin            On

  Dependencies                  zlib, boost, TBB, MaterialX, OpenSubdiv

Each item listed in Dependencies will be downloaded and compiled.

Build Output

After a successful compile all the build output is in the ../my-usd-build folder. What the build includes will depend on the parameters passed to build_usd.py.

On success you should get a message like this one

Success! To use USD, please ensure that you have:

    The following in your PYTHONPATH environment variable:
    /Projects/github/rstelzleni/my-usd-build/lib/python

    The following in your PATH environment variable:
    /Projects/github/rstelzleni/my-usd-build/bin

Really only the PYTHONPATH needs to be updated to use USD python modules, or to run usdcat or usdview. On Linux and Mac updating PATH is only necessary to make tools available at the command line, but on Windows it is also necessary to run things.

The build output will contain source code from dependencies, intermediate build files, object files and configuration. This amounts to a lot of extra size. You can separate out the files that need to be in the install from the source and intermediate files using a few command line flags, like so:

python build_scripts/build_usd.py --build=../my-usd-build-2-intermediate --src=../my-usd-build-2-src ../my-usd-build-2

If I build USD v24.05 with these two command lines on my Macbook I get directories with these sizes:

3.7G	my-usd-build
835M	my-usd-build-2
1.7G	my-usd-build-2-intermediate
1.0G	my-usd-build-2-src

As you can see, this separates out a full 2.7G of files that are only needed for incremental builds. The files needed to run USD and the related tools are all in my-usd-build-2, so in theory you could delete everything in the intermediate and src folders once your build was working.

If you need to relocate the install it's best to copy the install directory whole. USD's Plug library requires configuration files that are located at relative path locations to the shared libraries in USD. By copying everything together you can ensure the relative paths don't break. If my-usd-build or my-usd-build-2 was moved to a new folder, and the PYTHONPATH and PATH was updated to point to that folder, then usdview and other tools should still work from that new location.

Building with CMake Directly

If build_usd.py serves your needs that's great! It's a good tool and covers most use cases. If you need to build for an exotic or very specific platform though it might not do the job. In that case you can bypass the python script and build with CMake directly.

I won't go too in depth into this here, if there's demand for it this could be a whole dedicated article. When I need to build with CMake I find it useful to run build_usd.py anyway, and use it to identify the dependencies, versions and build flags that the python script would have used.

Pitfalls

Here are a few common errors I've encountered when building. If you run into these, I'll at least list the first things I try to get things working.

  • ERROR: PySide's user interface compiler was not found – please install PySide2 or PySide6 and adjust your PATH. (Note that this program may be named pyside6-uic or pyside2-uic depending on your platform)
    • If you're building usdview this is pretty common. One of these uic programs needs to be available in your path, and may not be even if pyside is installed on some platforms. The fix is to locate the uic version you have and add it to the path.
  • fatal error: patchlevel.h: No such file or directory
    • I often see this one in docker containers when trying to build boost, it usually means I forgot to install the python-dev package or its equivalent on the platform.
  • Build warnings. There can be many, stemming from boost and other packages. I have not created a comprehensive list to disable them, but it would be an interesting thing to have.