diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e458e6..8f0310af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,25 +54,6 @@ if(EMSCRIPTEN) option(MUJOCO_BUILD_TESTS_WASM "Build tests for WASM bindings" ON) endif() -# Option to provide a path to an existing USD build directory or to Houdini HFS directory. -set(USD_DIR "" CACHE PATH "Path to an existing USD build directory.") -set(HOUDINI_HFS_DIR "" CACHE PATH "Path to Houdini HFS directory to build USD plugins against.") -if(USD_DIR) - if(EXISTS "${USD_DIR}") - # If the path is provided, set MUJOCO_WITH_USD to ON and add the path to CMAKE_PREFIX_PATH. - set(MUJOCO_WITH_USD ON CACHE BOOL "Build with OpenUSD" FORCE) - list(PREPEND CMAKE_PREFIX_PATH "${USD_DIR}") - message(STATUS "Using custom USD build directory: ${USD_DIR}") - else() - message(WARNING "Invalid path provided for USD_DIR: ${USD_DIR}") - endif() -elseif(HOUDINI_HFS_DIR) - if(EXISTS "${HOUDINI_HFS_DIR}") - set(MUJOCO_WITH_USD ON CACHE BOOL "Build with OpenUSD" FORCE) - message(STATUS "Building Mujoco USD against Houdini HFS: ${HOUDINI_HFS_DIR}") - endif() -endif() - if(APPLE AND (MUJOCO_BUILD_EXAMPLES OR MUJOCO_BUILD_SIMULATE)) enable_language(OBJC) enable_language(OBJCXX) @@ -243,7 +224,24 @@ if(MUJOCO_BUILD_EXAMPLES) endif() if(MUJOCO_WITH_USD) - target_compile_definitions(mujoco PUBLIC mjUSEUSD) + include(third_party_deps/openusd) + + get_filename_component(USD_INSTALL_ROOT "${pxr_DIR}/lib" ABSOLUTE) + install( + DIRECTORY ${USD_INSTALL_ROOT}/ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + if(APPLE) + set_target_properties(mujoco PROPERTIES + BUILD_RPATH "${USD_INSTALL_ROOT}" + INSTALL_RPATH "@loader_path") + elseif(UNIX) + set_target_properties(mujoco PROPERTIES + BUILD_RPATH "${USD_INSTALL_ROOT}" + INSTALL_RPATH "$ORIGIN") + endif() + add_subdirectory(src/experimental/usd) endif() diff --git a/cmake/third_party_deps/openusd.cmake b/cmake/third_party_deps/openusd.cmake new file mode 100644 index 00000000..861ea365 --- /dev/null +++ b/cmake/third_party_deps/openusd.cmake @@ -0,0 +1,38 @@ +# Copyright 2025 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Find OpenUSD package. The user can either provide pxr_DIR to use their own +# OpenUSD installation or they can build external_dependencies. +# +# We use QUIET here to provide a better error message when pxr is not found. +find_package(pxr + QUIET + HINTS "${CMAKE_BINARY_DIR}/_deps/openusd-build" +) + +if(NOT pxr_FOUND) + message(FATAL_ERROR + "-----------------------------------------------------------\n" + "USD Configuration Error:\n${pxr_NOT_FOUND_MESSAGE}\n" + "If you have built USD yourself, provide -Dpxr_DIR=your_pxr_install_dir' \n" + "Otherwise you can build cmake/third_party_deps/openusd:\n" + "cd ~/mujoco\n" + "cmake -Bcmake/third_party_deps/openusd/build cmake/third_party_deps/openusd -DBUILD_USD=True\n" + "cmake --build cmake/third_party_deps/openusd/build\n" + "cmake -Bbuild -S. -DMUJOCO_WITH_USD=True\n" + "cmake --build build\n" + "cmake --install build" + "-----------------------------------------------------------" + ) +endif() diff --git a/cmake/third_party_deps/openusd/CMakeLists.txt b/cmake/third_party_deps/openusd/CMakeLists.txt new file mode 100644 index 00000000..37676017 --- /dev/null +++ b/cmake/third_party_deps/openusd/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright 2025 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +cmake_minimum_required(VERSION "3.16") + +option(BUILD_USD OFF "Build OpenUSD") +project(openusd-dependency) + +if (BUILD_USD) + include(ExternalProject) + + set(DEPS_DIR ${CMAKE_BINARY_DIR}/../../../../build/_deps) + + ExternalProject_Add(openusd + GIT_REPOSITORY https://github.com/PixarAnimationStudios/USD.git + GIT_TAG v25.11 + PREFIX openusd + BUILD_IN_SOURCE 0 + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" + SOURCE_DIR ${DEPS_DIR}/openusd-src + BINARY_DIR ${DEPS_DIR}/openusd-build + INSTALL_DIR ${DEPS_DIR}/openusd-build + BUILD_COMMAND python3 ${DEPS_DIR}/openusd-src/build_scripts/build_usd.py + --build-shared + --no-examples + --no-tools + --no-ptex + --no-prman + --no-openimageio + --no-opencolorio + --no-alembic + --no-draco + --no-materialx + --no-tutorials + --no-tests + --no-docs + --no-imaging + --no-python + --no-usdValidation + + ) +endif() diff --git a/simulate/CMakeLists.txt b/simulate/CMakeLists.txt index 16756b44..7dcf7fdc 100644 --- a/simulate/CMakeLists.txt +++ b/simulate/CMakeLists.txt @@ -185,7 +185,7 @@ if(SIMULATE_BUILD_EXECUTABLE) target_link_libraries(simulate "-framework CoreVideo") endif() - if (MUJOCO_WITH_USD) + if (BUILD_WITH_USD) # pxr/usd/tf/hashset.h might include deprecated headers so disable this check # when compiling with USD enabled. target_compile_options( @@ -265,8 +265,13 @@ if(SIMULATE_BUILD_EXECUTABLE) MUJOCO_ENABLE_RPATH ) - if (MUJOCO_WITH_USD) - target_compile_definitions(simulate PUBLIC mjUSEUSD) + if (BUILD_WITH_USD) + # pxr/usd/tf/hashset.h might include deprecated headers so disable this check + # when compiling with USD enabled. + target_compile_options( + simulate + PRIVATE -Wno-deprecated + ) # Add support to RPATH for the samples. target_add_rpath( @@ -275,10 +280,13 @@ if(SIMULATE_BUILD_EXECUTABLE) INSTALL_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" LIB_DIRS - ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/mujocoUsd ${USD_DIR}/lib DEPENDS MUJOCO_ENABLE_RPATH ) + + # Do we need this? + #target_link_options(simulate PRIVATE -rpath=${pxr_DIR}/lib) + endif() if(NOT MUJOCO_SIMULATE_USE_SYSTEM_GLFW) diff --git a/src/experimental/usd/CMakeLists.txt b/src/experimental/usd/CMakeLists.txt index 72b8eab6..09b26a84 100644 --- a/src/experimental/usd/CMakeLists.txt +++ b/src/experimental/usd/CMakeLists.txt @@ -18,7 +18,7 @@ set(MJCF_PLUGIN_TARGET_NAME usdMjcf) set(MJC_PHYSICS_PLUGIN_TARGET_NAME mjcPhysics) # Installation directory for USD plugins -set(MJ_USD_INSTALL_DIR_LIB ${CMAKE_INSTALL_LIBDIR}/mujocoUsd) +set(MJ_USD_INSTALL_DIR_LIB ${CMAKE_INSTALL_LIBDIR}/mujoco-usd-resources) # Common OpenUSD libraries set(OPENUSD_CORE_LIBS @@ -41,7 +41,7 @@ function(configure_and_install_usd_plugin_info plugin_name source_subpath instal endif() set(PLUG_INFO_LIBRARY_PATH "../../${LIB_PREFIX}${plugin_name}${CMAKE_SHARED_LIBRARY_SUFFIX}") - set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/${install_base_dir}/resources/${plugin_name}") + set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/${install_base_dir}/${plugin_name}") set(OUTPUT_FILE "${OUTPUT_DIR}/plugInfo.json") # Create the output directory if it doesn't exist @@ -55,7 +55,7 @@ function(configure_and_install_usd_plugin_info plugin_name source_subpath instal ) install(FILES "${OUTPUT_FILE}" - DESTINATION "${install_base_dir}/resources/${plugin_name}" + DESTINATION "${install_base_dir}/${plugin_name}" ) endfunction() @@ -82,6 +82,7 @@ function(configure_houdini_target target_name link_scope include_scope) ${PXR_LIB_PREFIX}usdShade ${PXR_LIB_PREFIX}usdLux ${PXR_LIB_PREFIX}usdGeom + ${PXR_LIB_PREFIX}usdImaging ${PXR_LIB_PREFIX}usdPhysics tbb hboost_${USD_MJCF_PYTHON_LIB_NUMBER} @@ -101,56 +102,9 @@ function(configure_houdini_target target_name link_scope include_scope) endfunction() ## usdMjcf -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) - -# The list of RPATHs: -# 1. $ORIGIN: For libmjcPhysics.so (since it's in the same install dir) -# 2. Path to OpenUSD libraries: Typically ${USD_DIR}/lib -# 3. Path to MuJoCo library: Assuming it's in ${MUJOCO_INSTALL_DIR}/lib -if(APPLE) - set(RPATH_LIST "@loader_path") - # Add OpenUSD lib to RPATH for macOS - if(DEFINED USD_DIR AND EXISTS "${USD_DIR}/lib") - list(APPEND RPATH_LIST "${USD_DIR}/lib") - endif() - # Add MuJoCo lib to RPATH for macOS - if(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/lib") - list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/lib") - endif() - - string(JOIN ":" CMAKE_INSTALL_RPATH "${RPATH_LIST}") # macOS uses colon for RPATH separator - message(STATUS "Final CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}") -elseif(UNIX) - - # For adjacent libs. - set(RPATH_LIST "\$ORIGIN") - - # Add OpenUSD library directory - if(DEFINED USD_DIR AND EXISTS "${USD_DIR}/lib") - list(APPEND RPATH_LIST "${USD_DIR}/lib") - message(STATUS "Adding OpenUSD lib to RPATH: ${USD_DIR}/lib") - else() - message(WARNING "USD_DIR is not defined or ${USD_DIR}/lib does not exist. OpenUSD libraries might not be found via RPATH.") - endif() - - # Add MuJoCo library directory - if(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/lib") - list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/lib") - message(STATUS "Adding MuJoCo lib to RPATH: ${MUJOCO_INSTALL_DIR}/lib") - elseif(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/bin") - list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/bin") - message(STATUS "Adding MuJoCo bin to RPATH: ${MUJOCO_INSTALL_DIR}/bin") - endif() - - # Set the final RPATH for installation - string(JOIN ";" CMAKE_INSTALL_RPATH "${RPATH_LIST}") - message(STATUS "Final CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}") -endif() - set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) add_library(${MJCF_PLUGIN_TARGET_NAME} SHARED) -add_library(mujoco::usd::mjcf ALIAS ${MJCF_PLUGIN_TARGET_NAME}) target_sources(${MJCF_PLUGIN_TARGET_NAME} PRIVATE plugins/mjcf/mjcf_file_format.cc plugins/mjcf/mjcf_file_format.h @@ -167,7 +121,7 @@ target_include_directories(${MJCF_PLUGIN_TARGET_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/plugins" ) -## mjcPhysics +## ----- mjcPhysics ----- add_library(${MJC_PHYSICS_PLUGIN_TARGET_NAME} SHARED) target_sources(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE @@ -191,7 +145,7 @@ target_include_directories(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PUBLIC $ ) -## mj_usd +## ----- mujoco USD utils ----- target_sources(mujoco PRIVATE kinematic_tree.cc @@ -211,42 +165,61 @@ target_compile_options( PRIVATE -Wno-deprecated ) -if (USD_DIR) - find_package(pxr REQUIRED) +# Configure RPATH for macOS and UNIX. +if(APPLE) + set(RPATH_LIST "@loader_path") + # Add OpenUSD lib to RPATH for macOS + if(DEFINED pxr_DIR AND EXISTS "${pxr_DIR}/lib") + list(APPEND RPATH_LIST "${pxr_DIR}/lib") + endif() + # Add MuJoCo lib to RPATH for macOS + if(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/lib") + list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/lib") + endif() - target_link_libraries(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE - ${OPENUSD_CORE_LIBS} - ) + string(JOIN ":" CMAKE_INSTALL_RPATH "${RPATH_LIST}") # macOS uses colon for RPATH separator + message(STATUS "Final CMAKE_INSTALL_RPATH: ${CMAKE_INSTALL_RPATH}") +elseif(UNIX) - target_link_libraries(${MJCF_PLUGIN_TARGET_NAME} PRIVATE - ${OPENUSD_CORE_LIBS} - mujoco - tinyxml2 - ${MJC_PHYSICS_PLUGIN_TARGET_NAME} - ) + # For adjacent libs. + set(RPATH_LIST "\$ORIGIN") - target_link_libraries(mujoco PUBLIC - ${OPENUSD_CORE_LIBS} - ${MJC_PHYSICS_PLUGIN_TARGET_NAME} - ) -elseif (HOUDINI_HFS_DIR) - message(STATUS "Configuring for Houdini target...") + # Add OpenUSD library directory + if(DEFINED pxr_DIR AND EXISTS "${pxr_DIR}/lib") + list(APPEND RPATH_LIST "${pxr_DIR}/lib") + message(STATUS "Adding OpenUSD lib to RPATH: ${pxr_DIR}/lib") + else() + message(WARNING "pxr_DIR is not defined or ${pxr_DIR}/lib does not exist. OpenUSD libraries might not be found via RPATH.") + endif() - # In Houdini, the Houdini package we would typically use via find_package - # does not have all the USD dependencies that we need (namely UsdPhysics) - # so we need to manually link all the required libraries. - configure_houdini_target(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE PRIVATE) - configure_houdini_target(${MJCF_PLUGIN_TARGET_NAME} PRIVATE PRIVATE) - - # Re-add inter-plugin dependencies after Houdini-specific linking - target_link_libraries(${MJCF_PLUGIN_TARGET_NAME} PRIVATE ${MJC_PHYSICS_PLUGIN_TARGET_NAME}) + # Add MuJoCo library directory + if(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/lib") + list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/lib") + elseif(DEFINED MUJOCO_INSTALL_DIR AND EXISTS "${MUJOCO_INSTALL_DIR}/bin") + list(APPEND RPATH_LIST "${MUJOCO_INSTALL_DIR}/bin") + endif() + # Set the final RPATH for installation + string(JOIN ";" CMAKE_INSTALL_RPATH "${RPATH_LIST}") endif() -## Installation +target_link_libraries(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE + ${OPENUSD_CORE_LIBS} +) -message(STATUS "Mujoco USD plugins will be installed to: ${CMAKE_INSTALL_PREFIX}/${MJ_USD_INSTALL_DIR_LIB}") -message(STATUS "Make sure PXR_PLUGINPATH_NAME includes: ${CMAKE_INSTALL_PREFIX}/${MJ_USD_INSTALL_DIR_LIB}/*/resources") +target_link_libraries(${MJCF_PLUGIN_TARGET_NAME} PRIVATE + ${OPENUSD_CORE_LIBS} + mujoco + tinyxml2 + ${MJC_PHYSICS_PLUGIN_TARGET_NAME} +) + +target_link_libraries(mujoco PUBLIC + ${OPENUSD_CORE_LIBS} + ${MJC_PHYSICS_PLUGIN_TARGET_NAME} +) + +## Installation # Generate and install plugInfo.json for each plugin configure_and_install_usd_plugin_info( @@ -263,7 +236,7 @@ configure_and_install_usd_plugin_info( # Install specific resources that are not plugInfo.json (like generatedSchema.usda) install(FILES mjcPhysics/generatedSchema.usda - DESTINATION ${MJ_USD_INSTALL_DIR_LIB}/resources/mjcPhysics + DESTINATION ${MJ_USD_INSTALL_DIR_LIB}/mjcPhysics ) # Install shared libraries @@ -271,5 +244,5 @@ install(TARGETS ${MJCF_PLUGIN_TARGET_NAME} ${MJC_PHYSICS_PLUGIN_TARGET_NAME} EXPORT ${PROJECT_NAME} - LIBRARY DESTINATION ${MJ_USD_INSTALL_DIR_LIB} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) diff --git a/test/experimental/CMakeLists.txt b/test/experimental/CMakeLists.txt index 92b73f58..2d0d5392 100644 --- a/test/experimental/CMakeLists.txt +++ b/test/experimental/CMakeLists.txt @@ -13,9 +13,7 @@ # limitations under the License. # Only support testing when building against a standalone version of USD. -if(MUJOCO_WITH_USD AND USD_DIR) - find_package(pxr REQUIRED) - +if(MUJOCO_WITH_USD) add_library(usd_test_utils STATIC usd/test_utils.h usd/test_utils.cc) target_include_directories(usd_test_utils PUBLIC ${MUJOCO_TEST_INCLUDE}) target_compile_definitions(usd_test_utils PUBLIC MJSTATIC)