Building

This document describes how to alter a Hydra Render Delegate to build against Katana from an external location without requiring to rebuild USD. To enable use inside the Katana Hydra Viewer inside the Katana session, we will go through the steps of setting up the delegate folders, building the delegate, and then installing the delegate, along with some common issues, and potential remedies for those.

Setting up the Delegate Folders

The first step is to ensure that the delegate’s folders are set up such that when we try and build, we have all the parts from USD we need and all the required pre-requisite libraries.

  1. Download and build any other required libraries, for example TBB and the renderer for the delegate you’re building (in this example Embree).

  2. Create the folder you want to clone your delegate into, e.g mkdir EmbreeDelegate.

  3. Clone your delegate into the folder EmbreeDelegate such that the folder with the delegate code is one level away, e.g the hdEmbree folder would be at EmbreeDelegate/hdEmbree.

  4. Enter the EmbreeDelegate folder and copy the cmake folder from USD 19.05 or the version of USD built into the version of Katana you are using, which is shown in Katana’s About dialog and in the release notes.
    1. You can find the cmake folder here: https://github.com/PixarAnimationStudios/USD/tree/v19.05/cmake. Just make sure to check out the correct branch via the Git tags.
    2. This folder is needed as it contains the CMake functions for pxr_plugin which most delegates use by default.
  5. Copy the CMakeLists.txt file attached below into your EmbreeDelegate folder.

project(usd)

if (WIN32)
    cmake_minimum_required(VERSION 3.1.1)
else()
    cmake_minimum_required(VERSION 2.8.8)
endif()

if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
    if (WIN32)
        message(FATAL_ERROR "Compiler does not support 64-bit builds. "
                "If you are using Visual Studio, make sure you are in the "
                "x64 command prompt and have specified the Win64 cmake "
                "generator (e.g., -G \"Visual Studio 14 2015 Win64\")")
    else()
        message(FATAL_ERROR "Compiler does not support 64-bit builds.")
    endif()
endif()

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
                    ${CMAKE_SOURCE_DIR}/cmake/defaults
                    ${CMAKE_SOURCE_DIR}/cmake/modules
                    ${CMAKE_SOURCE_DIR}/cmake/macros)

include(Options)
include(ProjectDefaults)
include(Packages)

find_package(GLEW REQUIRED)
find_package(Boost REQUIRED)
find_package(TBB REQUIRED)

# Go through all the USD libs and find the full paths to the libraries for
# linking.
# Add the library path to the interface for each library such that we don't
# need to edit the CMakeLists.txt of the delegate
set(USD_LIBS
    arch;tf;gf;js;trace;work;plug;vt;ar;kind;sdf;ndr;sdr;pcp;usd;usdGeom;usdVol;usdLux;usdShade;usdHydra;usdRi;usdSkel;usdUI;usdUtils;garch;hf;hio;cameraUtil;pxOsd;glf;hd;hdSt;hdx;usdImaging;usdImagingGL;usdSkelImaging;usdVolImaging;usdviewq
)
set(USD_LIB_EXTENSION .so)
if(WIN32)
    set(USD_LIB_EXTENSION .lib)
endif()
set(usd_lib_prefix USD_)
set(usd_lib_suffix _LIB)
foreach(lib ${USD_LIBS})
    message("finding lib = ${lib}${USD_LIB_EXTENSION}")
    find_library(${usd_lib_prefix}${lib}${usd_lib_suffix}
        NAMES
            ${PXR_LIB_PREFIX}${lib}${USD_LIB_EXTENSION}
        HINTS
            ${USD_LIBRARY_DIR}
            ${USD_LIBRARY_DIR}/../plugin/usd/
    )
    add_library(${lib} INTERFACE IMPORTED)
    set_target_properties(${lib}
        PROPERTIES
        INTERFACE_LINK_LIBRARIES ${${usd_lib_prefix}${lib}${usd_lib_suffix}}
    )
    message(" ${${usd_lib_prefix}${lib}${usd_lib_suffix}}")
    list(APPEND ALL_USD_LIBS ${${usd_lib_prefix}${lib}${usd_lib_suffix}})
endforeach()

# Add the location of boost and pxr headers. These are often needed as
# headers included by the delegate usually require finding these headers
# as well.
include_directories(${BOOST_INCLUDE_DIR})
include_directories(${PXR_INCLUDE_DIR})
include_directories(${PYTHON_INCLUDE_DIR})
include_directories(${GLEW_INCLUDE_DIR})

# CXXDefaults will set a variety of variables for the project.
# Consume them here. This is an effort to keep the most common
# build files readable.
include(CXXDefaults)
add_definitions(${_PXR_CXX_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${_PXR_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")

include(Public)

# USD requires this to be a target...
if (NOT TARGET shared_libs)
    add_custom_target(shared_libs)
endif ()

# Add subdirectory for the delegate you are building
# Ensuring we run in the start and stop pxr building steps
# otherwise ../hdEmbree.so isn't added as the library path in the
# plugInfo.json
pxr_core_prologue()
add_subdirectory(hdEmbree)
pxr_core_epilogue()

Make sure to edit any values here which make sense to your build including the add_subdirectory to match your delegate relative path from step 3. Your structure should now be set up and ready to build!

Building the Delegate

Building the delegate requires a few CMake definitions to be set up in order to make the delegate build externally to the USD source, and to build against the USD shared libraries shipped with Katana. Below, we have included an example of the CMake build script we made for Linux in order to build Embree externally from USD source. This script should be placed and run from the root folder of your delegate setup, e.g EmbreeDelegate/build_script.sh.

# Ensure 100% clean build each time.
rm -rf build
mkdir build
cd build

KATANA_ROOT=</path/to/Katana>
INSTALL_PREFIX=<where you want it to be installed, usually $PWD/../install>
EMBREE_ROOT=</path/to/Embree>

# We use the <Library>_FOUND=1 to ensure we have more control over finding libraries required to build the delegate.
# Otherwise you can look into the cmake folder provided by USD and edit this to add your own custom libraries if you
# differ from the default build USD expects.
cmake ../ \
    -DCMAKE_BUILD_TYPE="Release" \
    -DPXR_BUILD_IMAGING="OFF" \
    -DPXR_ENABLE_PYTHON_SUPPORT="OFF" \
    -DPXR_BUILD_TESTS="OFF" \
    -DBUILD_SHARED_LIBS="ON" \
    -DPXR_LIB_PREFIX="Fn" \
    -DPXR_BUILD_EMBREE_PLUGIN=1 \
    -DEMBREE_FOUND=1 \
    -DEMBREE_LIBRARY=${EMBREE_ROOT}/lib64/libembree.so \
    -DEMBREE_INCLUDE_DIR=${EMBREE_ROOT}/include \
    -DPXR_INCLUDE_DIR=${KATANA_ROOT}/include \
    -DUSD_LIBRARY_DIR=${KATANA_ROOT}/bin \
    -DPYTHON_INCLUDE_DIR=${KATANA_ROOT}/bin/python2.7/include/python2.7 \
    -DTBB_FOUND=1 \
    -DTBB_INCLUDE_DIR= <DIR to TBB include directory> \
    -DTBB_LIBRARIES=<path to tbb library>;<path to tbbmalloc library> \
    -DBOOST_ROOT= <Dir to Boost root directory> \
    -DBOOST_INCLUDE_DIR=<Dir to Boost include directory> \
    -DBoost_USE_STATIC_LIBS=OFF \
    -DGLEW_INCLUDE_DIR=<Dir to GLEW include folder> \
    -DGLEW_LIBRARY=<Path to GLEW library> \
    -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}
cmake --build . --target install -- -j8

There are a few things in the build script above which can be changed including the ability to explicitly pass all the required libraries rather than relying upon USD’s CMake searches, or CMake config files themselves for third-party libraries.