diff --git a/cmake/libwebp-apple-float16.patch b/cmake/libwebp-apple-float16.patch new file mode 100644 index 00000000..a2af3e5f --- /dev/null +++ b/cmake/libwebp-apple-float16.patch @@ -0,0 +1,8 @@ +diff --git a/cmake/cpu.cmake b/cmake/cpu.cmake +--- a/cmake/cpu.cmake ++++ b/cmake/cpu.cmake +@@ -121,3 +121,3 @@ + # Explicitly disable SIMD. +- if(SIMD_DISABLE_FLAGS) ++ if(SIMD_DISABLE_FLAGS AND NOT APPLE) + list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) diff --git a/cmake/third_party_deps/filament.cmake b/cmake/third_party_deps/filament.cmake index 047ef5b8..ce228551 100644 --- a/cmake/third_party_deps/filament.cmake +++ b/cmake/third_party_deps/filament.cmake @@ -32,6 +32,11 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include cstring -include optional") endif() +# Filament generates deprecated warnings on MacOS. +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations") +endif() + set(FILAMENT_ENABLE_EXPERIMENTAL_GCC_SUPPORT ON) set(FILAMENT_SKIP_SDL2 ON) set(FILAMENT_USE_EXTERNAL_ABSL ON) diff --git a/cmake/third_party_deps/libwebp.cmake b/cmake/third_party_deps/libwebp.cmake index 4eadcc2e..b971c029 100644 --- a/cmake/third_party_deps/libwebp.cmake +++ b/cmake/third_party_deps/libwebp.cmake @@ -20,9 +20,21 @@ mark_as_advanced(MUJOCO_DEP_VERSION_libwebp) include(FindOrFetch) +set(LIBWEBP_PATCH_COMMAND + git apply --reject --whitespace=fix ${mujoco_SOURCE_DIR}/cmake/libwebp-apple-float16.patch +) + +set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) +set(BUILD_SHARED_LIBS OFF) + fetchpackage( PACKAGE_NAME libwebp GIT_REPO https://github.com/webmproject/libwebp.git GIT_TAG ${MUJOCO_DEP_VERSION_libwebp} TARGETS webp + PATCH_COMMAND ${LIBWEBP_PATCH_COMMAND} ) + +set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD}) + + diff --git a/python/mujoco/CMakeLists.txt b/python/mujoco/CMakeLists.txt index 2e7a5ea6..e1169e57 100644 --- a/python/mujoco/CMakeLists.txt +++ b/python/mujoco/CMakeLists.txt @@ -89,6 +89,7 @@ if(NOT TARGET mujoco) ${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A/libmujoco.3.10.0.dylib ) target_compile_options(mujoco INTERFACE -F${MUJOCO_FRAMEWORK}) + set(MUJOCO_INCLUDE "${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A/Headers") endif() endif() @@ -132,8 +133,12 @@ endif() # =================== MUJOCO PLATFORM STATIC LIBRARY ========================== if(NOT TARGET mujoco::platform) + set(MUJOCO_PLATFORM_HINTS ${MUJOCO_LIBRARY_DIR}) + if(MUJOCO_FRAMEWORK) + list(APPEND MUJOCO_PLATFORM_HINTS "${MUJOCO_FRAMEWORK}/mujoco.framework/Versions/A") + endif() find_library( - MUJOCO_PLATFORM_LIBRARY mujoco_platform HINTS ${MUJOCO_LIBRARY_DIR} + MUJOCO_PLATFORM_LIBRARY mujoco_platform HINTS ${MUJOCO_PLATFORM_HINTS} ) if(MUJOCO_PLATFORM_LIBRARY) message(STATUS "Found mujoco_platform library at ${MUJOCO_PLATFORM_LIBRARY}") @@ -141,8 +146,9 @@ if(NOT TARGET mujoco::platform) set_target_properties(mujoco_platform PROPERTIES IMPORTED_LOCATION "${MUJOCO_PLATFORM_LIBRARY}") add_library(mujoco::platform ALIAS mujoco_platform) + set(PLATFORM_INCLUDES "${MUJOCO_INCLUDE}" "${MUJOCO_INCLUDE}/mujoco" "${MUJOCO_INCLUDE}/SDL2") set_target_properties(mujoco_platform PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${MUJOCO_INCLUDE};${MUJOCO_INCLUDE}/mujoco;${MUJOCO_INCLUDE}/SDL2" + INTERFACE_INCLUDE_DIRECTORIES "${PLATFORM_INCLUDES}" ) target_compile_features(mujoco_platform INTERFACE cxx_std_20) @@ -177,7 +183,7 @@ if(NOT TARGET mujoco::platform) zstd z ) - find_library(DEP_PATH_${dep_lib} ${dep_lib} HINTS ${MUJOCO_LIBRARY_DIR}) + find_library(DEP_PATH_${dep_lib} ${dep_lib} HINTS ${MUJOCO_PLATFORM_HINTS}) if(DEP_PATH_${dep_lib}) add_library(mujoco::dep::${dep_lib} STATIC IMPORTED GLOBAL) set_target_properties(mujoco::dep::${dep_lib} PROPERTIES @@ -191,6 +197,22 @@ if(NOT TARGET mujoco::platform) if(UNIX AND NOT APPLE) list(APPEND PLATFORM_DEPS pthread dl rt) endif() + if(APPLE) + list(APPEND PLATFORM_DEPS + "-framework Cocoa" + "-framework IOKit" + "-framework Carbon" + "-framework ForceFeedback" + "-framework CoreVideo" + "-framework CoreAudio" + "-framework AudioToolbox" + "-framework Metal" + "-framework GameController" + "-framework CoreHaptics" + "-framework AVFoundation" + "-framework QuartzCore" + ) + endif() set_target_properties(mujoco_platform PROPERTIES INTERFACE_LINK_LIBRARIES "${PLATFORM_DEPS}") endif() @@ -494,6 +516,10 @@ target_link_libraries( structs_wrappers ) +if(APPLE) + set_target_properties(_structs PROPERTIES INTERPROCEDURAL_OPTIMIZATION FALSE) +endif() + if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/specs.cc.inc) add_custom_command( OUTPUT specs.cc.inc diff --git a/python/mujoco/experimental/studio/CMakeLists.txt b/python/mujoco/experimental/studio/CMakeLists.txt index 7b392f53..aad74f0d 100644 --- a/python/mujoco/experimental/studio/CMakeLists.txt +++ b/python/mujoco/experimental/studio/CMakeLists.txt @@ -83,3 +83,26 @@ if(UNIX AND NOT APPLE) target_link_options(${target} PRIVATE "-Wl,--allow-multiple-definition") endforeach() endif() + +if(APPLE) + set(STUDIO_PY_MODULES + parser + native_viewer_cc + renderer + ux + sim + dear_imgui + implot + ) + foreach(target ${STUDIO_PY_MODULES}) + if(TARGET ${target}) + add_custom_command( + TARGET ${target} + POST_BUILD + COMMAND + install_name_tool -add_rpath @loader_path/../../ $ + ) + endif() + endforeach() +endif() + diff --git a/src/experimental/studio/CMakeLists.txt b/src/experimental/studio/CMakeLists.txt index ef638a2e..bde8504d 100644 --- a/src/experimental/studio/CMakeLists.txt +++ b/src/experimental/studio/CMakeLists.txt @@ -54,24 +54,31 @@ function(configure_studio_target TARGET_NAME) mujoco::platform ) - file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets) + get_target_property(IS_BUNDLE ${TARGET_NAME} MACOSX_BUNDLE) + if(IS_BUNDLE) + set(STUDIO_ASSETS_DIR $/../Resources/assets) + else() + set(STUDIO_ASSETS_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets) + endif() add_custom_command( TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${STUDIO_ASSETS_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../_deps/opensans-src/fonts/ttf/OpenSans-Regular.ttf - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets + ${STUDIO_ASSETS_DIR} COMMENT "Copying OpenSans-Regular.ttf assets to build directory" ) add_custom_command( TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${STUDIO_ASSETS_DIR} COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../_deps/font_awesome-src/fonts/fontawesome-webfont.ttf - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets + ${STUDIO_ASSETS_DIR} COMMENT "Copying fontawesome-webfont.ttf to build directory" ) @@ -80,10 +87,11 @@ function(configure_studio_target TARGET_NAME) add_custom_command( TARGET ${TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${STUDIO_ASSETS_DIR} COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../src/render/filament/assets - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets + ${STUDIO_ASSETS_DIR} COMMENT "Copying Filament assets to build directory" ) endif() @@ -92,6 +100,13 @@ endfunction() # Desktop Studio target. if(NOT EMSCRIPTEN) add_executable(mujoco_studio) + if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS) + set_target_properties(mujoco_studio PROPERTIES + MACOSX_BUNDLE TRUE + INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/../../.." + BUILD_WITH_INSTALL_RPATH TRUE + ) + endif() target_sources(mujoco_studio PRIVATE main.cc) configure_studio_target(mujoco_studio) install( @@ -99,10 +114,13 @@ if(NOT EMSCRIPTEN) RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT studio BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT studio ) - install( - DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets" - DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT studio - ) + get_target_property(IS_BUNDLE mujoco_studio MACOSX_BUNDLE) + if(NOT IS_BUNDLE) + install( + DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets" + DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT studio + ) + endif() endif() # WASM Live target. diff --git a/src/experimental/studio/main.cc b/src/experimental/studio/main.cc index 6d273966..7fa7afe1 100644 --- a/src/experimental/studio/main.cc +++ b/src/experimental/studio/main.cc @@ -42,6 +42,10 @@ std::string Resolve(std::string_view path) { if (exe_dir.empty()) { return std::string("assets/") + std::string(subpath); } + std::filesystem::path resources_dir = exe_dir.parent_path() / "Resources"; + if (std::filesystem::exists(resources_dir / "assets")) { + return (resources_dir / "assets" / subpath).string(); + } return (exe_dir / "assets" / subpath).string(); }