diff --git a/CMakeLists.txt b/CMakeLists.txt index c61a1b6f..b1facb20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ enable_language(CXX) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") option(MUJOCO_BUILD_EXAMPLES "Build samples for MuJoCo" ON) +option(MUJOCO_BUILD_SIMULATE "Build simulate library for MuJoCo" ON) option(MUJOCO_BUILD_TESTS "Build tests for MuJoCo" ON) option(MUJOCO_TEST_PYTHON_UTIL "Build and test utility libraries for Python bindings" ON) @@ -47,6 +48,11 @@ if(APPLE AND MUJOCO_BUILD_EXAMPLES) enable_language(OBJCXX) endif() +if(APPLE AND MUJOCO_BUILD_SIMULATE) + enable_language(OBJC) + enable_language(OBJCXX) +endif() + include(MujocoOptions) include(MujocoMacOS) include(MujocoDependencies) @@ -156,6 +162,10 @@ if(MUJOCO_BUILD_EXAMPLES) add_subdirectory(sample) endif() +if(MUJOCO_BUILD_SIMULATE) + add_subdirectory(simulate) +endif() + if(BUILD_TESTING AND MUJOCO_BUILD_TESTS) enable_testing() add_subdirectory(test) diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index a29d2d43..4e4047f2 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -70,14 +70,6 @@ if(MUJOCO_HARDEN) endif() endif() -# Utility library -add_library(uitools STATIC) -target_sources(uitools PRIVATE uitools.h uitools.c) -target_include_directories(uitools PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -target_compile_options(uitools PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS}) -target_link_libraries(uitools PUBLIC glfw mujoco::mujoco) -target_link_options(uitools PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS}) - # Build sample binaries add_executable(compile compile.cc) target_compile_options(compile PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS}) @@ -126,41 +118,6 @@ target_link_libraries( ) target_link_options(record PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS}) -if(APPLE) - set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.icns) -elseif(WIN32) - set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/appicon.rc) -else() - set(SIMULATE_RESOURCE_FILES "") -endif() - -add_executable(simulate simulate.cc array_safety.h ${SIMULATE_RESOURCE_FILES}) -target_compile_options(simulate PUBLIC ${MUJOCO_SAMPLE_COMPILE_OPTIONS}) -if(WIN32) - add_custom_command( - TARGET simulate - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.ico - ${CMAKE_CURRENT_SOURCE_DIR} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E rm ${CMAKE_CURRENT_SOURCE_DIR}/mujoco.ico - ) -endif() - -target_link_libraries( - simulate - mujoco::mujoco - uitools - glfw - Threads::Threads -) -target_link_options(simulate PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS}) - -if(APPLE) - target_sources(simulate PRIVATE macos_save.mm) - target_link_libraries(simulate "-framework Cocoa") -endif() - if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS) set_target_properties( simulate @@ -225,7 +182,6 @@ if(_INSTALL_SAMPLES) record testspeed testxml - simulate INSTALL_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" LIB_DIRS @@ -241,7 +197,6 @@ if(_INSTALL_SAMPLES) record testspeed testxml - simulate EXPORT ${PROJECT_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT samples LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT samples diff --git a/simulate/CMakeLists.txt b/simulate/CMakeLists.txt new file mode 100644 index 00000000..6b7517e9 --- /dev/null +++ b/simulate/CMakeLists.txt @@ -0,0 +1,216 @@ +# Copyright 2021 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) + +# INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. +set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) +# Default to GLVND if available. +set(CMAKE_POLICY_DEFAULT_CMP0072 NEW) + +# This line has to appear before 'PROJECT' in order to be able to disable incremental linking +set(MSVC_INCREMENTAL_DEFAULT ON) + +project( + mujoco_simulate + VERSION 2.2.0 + DESCRIPTION "MuJoCo simulate binaries" + HOMEPAGE_URL "https://mujoco.org" +) + +enable_language(C) +enable_language(CXX) +if(APPLE) + enable_language(OBJC) + enable_language(OBJCXX) +endif() + +# Check if we are building as standalone project. +set(SIMULATE_STANDALONE OFF) +set(_INSTALL_SIMULATE ON) +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(SIMULATE_STANDALONE ON) + # If standalone, do not install the samples. + set(_INSTALL_SIMULATE OFF) +endif() + +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + +if(SIMULATE_STANDALONE) + include(SimulateOptions) +else() + enforce_mujoco_macosx_min_version() +endif() +include(SimulateDependencies) + +set(MUJOCO_SIMULATE_COMPILE_OPTIONS "${AVX_COMPILE_OPTIONS}" "${EXTRA_COMPILE_OPTIONS}") +set(MUJOCO_SIMULATE_LINK_OPTIONS "${EXTRA_LINK_OPTIONS}") + +if(MUJOCO_HARDEN) + if(WIN32) + set(MUJOCO_SIMULATE_LINK_OPTIONS "${MUJOCO_SIMULATE_LINK_OPTIONS}" -Wl,/DYNAMICBASE) + else() + set(MUJOCO_SIMULATE_COMPILE_OPTIONS "${MUJOCO_SIMULATE_COMPILE_OPTIONS}" -fPIE) + if(APPLE) + set(MUJOCO_SIMULATE_LINK_OPTIONS "${MUJOCO_SIMULATE_LINK_OPTIONS}" -Wl,-pie) + else() + set(MUJOCO_SIMULATE_LINK_OPTIONS "${MUJOCO_SIMULATE_LINK_OPTIONS}" -pie) + endif() + endif() +endif() + +# Utility library +add_library(uitools STATIC) +target_sources(uitools PRIVATE uitools.h uitools.c) +target_include_directories(uitools PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(uitools PUBLIC ${MUJOCO_SIMULATE_COMPILE_OPTIONS}) +target_link_libraries(uitools PUBLIC glfw mujoco::mujoco) +target_link_options(uitools PRIVATE ${MUJOCO_SIMULATE_LINK_OPTIONS}) + +# mjsimulate library +add_library(mjsimulate SHARED) +target_sources(mjsimulate PUBLIC simulate.h array_safety.h simulate.cc) +target_include_directories(mjsimulate PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(mjsimulate PUBLIC ${MUJOCO_SIMULATE_COMPILE_OPTIONS}) +target_link_libraries(mjsimulate PUBLIC glfw uitools mujoco::mujoco) # TODO is that right +target_link_options(mjsimulate PRIVATE ${MUJOCO_SIMULATE_LINK_OPTIONS}) + +# Build samples that require GLFW. + +if(APPLE) + set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.icns) +elseif(WIN32) + set(SIMULATE_RESOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/../dist/appicon.rc) +else() + set(SIMULATE_RESOURCE_FILES "") +endif() + +add_executable(simulate main.cc array_safety.h ${SIMULATE_RESOURCE_FILES}) +target_compile_options(simulate PUBLIC ${MUJOCO_SIMULATE_COMPILE_OPTIONS}) +if(WIN32) + add_custom_command( + TARGET simulate + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/../dist/mujoco.ico + ${CMAKE_CURRENT_SOURCE_DIR} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E rm ${CMAKE_CURRENT_SOURCE_DIR}/mujoco.ico + ) +endif() + +target_link_libraries( + simulate + mjsimulate + mujoco::mujoco + uitools + glfw + Threads::Threads +) +target_link_options(simulate PRIVATE ${MUJOCO_SAMPLE_LINK_OPTIONS}) + +if(APPLE) + target_sources(simulate PRIVATE macos_save.mm) + target_link_libraries(simulate "-framework Cocoa") +endif() + +if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS) + set_target_properties( + simulate + PROPERTIES INSTALL_RPATH @executable_path/../Frameworks + BUILD_WITH_INSTALL_RPATH TRUE + RESOURCE ${SIMULATE_RESOURCE_FILES} + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../dist/Info.plist.simulate.in + MACOSX_BUNDLE_BUNDLE_NAME "MuJoCo" + MACOSX_BUNDLE_GUI_IDENTIFIER "org.mujoco.mujoco" + MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} + MACOSX_BUNDLE_INFO_STRING ${PROJECT_VERSION} + MACOSX_BUNDLE_LONG_VERSION_STRING ${PROJECT_VERSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION} + MACOSX_BUNDLE_ICON_FILE "mujoco.icns" + MACOSX_BUNDLE_COPYRIGHT "Copyright 2021 DeepMind Technologies Limited." + ) + + macro(embed_in_bundle target) + add_dependencies(${target} simulate) + set_target_properties( + ${target} + PROPERTIES INSTALL_RPATH @executable_path/../Frameworks + BUILD_WITH_INSTALL_RPATH TRUE + RUNTIME_OUTPUT_DIRECTORY $ + ) + endmacro() + + # Embed mujoco.framework inside the App bundle ane move the icon file over too. + add_custom_command( + TARGET simulate + POST_BUILD + COMMAND mkdir -p $/../Frameworks + COMMAND rm -rf $/../Frameworks/mujoco.framework + COMMAND cp -a $/../../../mujoco.framework + $/../Frameworks/ + # Delete the symlink and the TBD, otherwise we can't sign and notarize. + COMMAND rm -rf $/../Frameworks/mujoco.framework/mujoco.tbd + COMMAND rm -rf + $/../Frameworks/mujoco.framework/Versions/A/libmujoco.dylib + ) +endif() + +# Do not install if macOS Bundles are created as RPATH is managed manually there. +if(APPLE AND MUJOCO_BUILD_MACOS_FRAMEWORKS) + set(_INSTALL_SIMULATE OFF) +endif() + +if(_INSTALL_SIMULATE) + + include(TargetAddRpath) + + # Add support to RPATH for the samples. + target_add_rpath( + TARGETS + simulate + INSTALL_DIRECTORY + "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" + LIB_DIRS + "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" + DEPENDS + MUJOCO_ENABLE_RPATH + ) + + install( + TARGETS simulate + EXPORT ${PROJECT_NAME} + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT simulate + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT simulate + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT simulate + BUNDLE DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT simulate + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT simulate + ) + + if(NOT MUJOCO_SIMULATE_USE_SYSTEM_GLFW) + # We downloaded GLFW. Depending if it is a static or shared LIBRARY we might + # need to install it. + get_target_property(MJ_GLFW_LIBRARY_TYPE glfw TYPE) + if(MJ_GLFW_LIBRARY_TYPE STREQUAL SHARED_LIBRARY) + install( + TARGETS glfw + EXPORT ${PROJECT_NAME} + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT simulate + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT simulate + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT simulate + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT simulate + ) + endif() + endif() +endif() diff --git a/simulate/Makefile b/simulate/Makefile index ecb4dbe6..ab4eaab4 100644 --- a/simulate/Makefile +++ b/simulate/Makefile @@ -2,12 +2,11 @@ # which is commonly available through your distro's package manager. # On Debian and Ubuntu, GLFW can be installed via `apt install libglfw3-dev`. -COMMON=-O2 -I../include -L../lib -std=c++11 -pthread -Wl,-rpath,'$$ORIGIN'/../lib +COMMON=-O2 -I../include -L../lib -std=c++17 -pthread -Wl,-no-as-needed -Wl,-rpath,'$$ORIGIN'/../lib all: $(CC) -c -O2 -fPIC -I../include uitools.c $(CXX) -c -O2 -fPIC -I../include simulate.cc - $(CXX) $(COMMON) -shared -Wl,-no-as-needed -Wl,-soname,libmjsimulate.so.2.1.5 -lmujoco -o libmjsimulate.so.2.1.5 simulate.o uitools.o - mv libmjsimulate.so.2.1.5 ../lib/libmjsimulate.so.2.1.5 - ln -sf ../lib/libmjsimulate.so.2.1.5 ../lib/libmjsimulate.so - $(CXX) $(COMMON) -Wl,-no-as-needed main.cc -lmjsimulate -lmujoco -lGL -lglfw -o ../bin/simulate + $(CXX) $(COMMON) -shared -lmujoco -o libmjsimulate.so simulate.o uitools.o + mv libmjsimulate.so ../lib/libmjsimulate.so + $(CXX) $(COMMON) main.cc -lmjsimulate -lmujoco -lGL -lglfw -o ../bin/simulate diff --git a/simulate/cmake/CheckAvxSupport.cmake b/simulate/cmake/CheckAvxSupport.cmake new file mode 100644 index 00000000..ab8ad644 --- /dev/null +++ b/simulate/cmake/CheckAvxSupport.cmake @@ -0,0 +1,53 @@ +# Copyright 2021 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. + +include(CheckCSourceCompiles) + +# Assigns compiler options to the given variable based on availability of AVX. +function(get_avx_compile_options OUTPUT_VAR) + message(VERBOSE "Checking if AVX is available...") + + if(MSVC) + set(CMAKE_REQUIRED_FLAGS "/arch:AVX") + else() + set(CMAKE_REQUIRED_FLAGS "-mavx") + endif() + + if(APPLE AND "x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES) + message(STATUS "Building x86_64 on macOS, forcing CAN_BUILD_AVX to TRUE.") + set(CAN_BUILD_AVX TRUE) + else() + check_c_source_compiles( + " + #include + int main(int argc, char* argv[]) { + __m256d ymm; + return 0; + } + " + CAN_BUILD_AVX + ) + endif() + + if(CAN_BUILD_AVX) + message(VERBOSE "Checking if AVX is available... AVX available.") + set("${OUTPUT_VAR}" + ${CMAKE_REQUIRED_FLAGS} + PARENT_SCOPE + ) + else() + message(VERBOSE "Checking if AVX is available... AVX not available.") + set("${OUTPUT_VAR}" PARENT_SCOPE) + endif() +endfunction() diff --git a/simulate/cmake/FindOrFetch.cmake b/simulate/cmake/FindOrFetch.cmake new file mode 100644 index 00000000..602601f5 --- /dev/null +++ b/simulate/cmake/FindOrFetch.cmake @@ -0,0 +1,139 @@ +# Copyright 2021 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. +# +#.rst: +# FindOrFetch +# ---------------------- +# +# Find or fetch a package in order to satisfy target dependencies. +# +# FindOrFetch([USE_SYSTEM_PACKAGE [ON/OFF]] +# [PACKAGE_NAME [name]] +# [LIBRARY_NAME [name]] +# [GIT_REPO [repo]] +# [GIT_TAG [tag]] +# [PATCH_COMMAND [cmd] [args]] +# [TARGETS [targets]] +# [EXCLUDE_FROM_ALL]) +# +# The command has the following parameters: +# +# Arguments: +# - ``USE_SYSTEM_PACKAGE`` one-value argument on whether to search for the +# package in the system (ON) or whether to fetch the library using +# FetchContent from the specified Git repository (OFF). Note that +# FetchContent variables will override this behaviour. +# - ``PACKAGE_NAME`` name of the system-package. Ignored if +# ``USE_SYSTEM_PACKAGE`` is ``OFF``. +# - ``LIBRARY_NAME`` name of the library. Ignored if +# ``USE_SYSTEM_PACKAGE`` is ``ON``. +# - ``GIT_REPO`` git repository to fetch the library from. Ignored if +# ``USE_SYSTEM_PACKAGE`` is ``ON``. +# - ``GIT_TAG`` tag reference when fetching the library from the git +# repository. Ignored if ``USE_SYSTEM_PACKAGE`` is ``ON``. +# - ``PATCH_COMMAND`` Specifies a custom command to patch the sources after an +# update. See https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add +# for details on the parameter. +# - ``TARGETS`` list of targets to be satisfied. If any of these targets are +# not currently defined, this macro will attempt to either find or fetch the +# package. +# - ``EXCLUDE_FROM_ALL`` if specified, the targets are not added to the ``all`` +# metatarget. +# +# Note: if ``USE_SYSTEM_PACKAGE`` is ``OFF``, FetchContent will be used to +# retrieve the specified targets. It is possible to specify any variable in +# https://cmake.org/cmake/help/latest/module/FetchContent.html#variables to +# override this macro behaviour. + +if(COMMAND FindOrFetch) + return() +endif() + +macro(FindOrFetch) + if(NOT FetchContent) + include(FetchContent) + endif() + + # Parse arguments. + set(options EXCLUDE_FROM_ALL) + set(one_value_args + USE_SYSTEM_PACKAGE + PACKAGE_NAME + LIBRARY_NAME + GIT_REPO + GIT_TAG + ) + set(multi_value_args PATCH_COMMAND TARGETS) + cmake_parse_arguments( + _ARGS + "${options}" + "${one_value_args}" + "${multi_value_args}" + ${ARGN} + ) + + # Check if all targets are found. + if(NOT _ARGS_TARGETS) + message(FATAL_ERROR "mujoco::FindOrFetch: TARGETS must be specified.") + endif() + + set(targets_found TRUE) + message(CHECK_START + "mujoco::FindOrFetch: checking for targets in package `${_ARGS_PACKAGE_NAME}`" + ) + foreach(target ${_ARGS_TARGETS}) + if(NOT TARGET ${target}) + message(CHECK_FAIL "target `${target}` not defined.") + set(targets_found FALSE) + break() + endif() + endforeach() + + # If targets are not found, use `find_package` or `FetchContent...` to get it. + if(NOT targets_found) + if(${_ARGS_USE_SYSTEM_PACKAGE}) + message(CHECK_START + "mujoco::FindOrFetch: finding `${_ARGS_PACKAGE_NAME}` in system packages..." + ) + find_package(${_ARGS_PACKAGE_NAME} REQUIRED) + message(CHECK_PASS "found") + else() + message(CHECK_START + "mujoco::FindOrFetch: Using FetchContent to retrieve `${_ARGS_LIBRARY_NAME}`" + ) + FetchContent_Declare( + ${_ARGS_LIBRARY_NAME} + GIT_REPOSITORY ${_ARGS_GIT_REPO} + GIT_TAG ${_ARGS_GIT_TAG} + GIT_SHALLOW FALSE + PATCH_COMMAND ${_ARGS_PATCH_COMMAND} + ) + if(${_ARGS_EXCLUDE_FROM_ALL}) + FetchContent_GetProperties(${_ARGS_LIBRARY_NAME}) + if(NOT ${${_ARGS_LIBRARY_NAME}_POPULATED}) + FetchContent_Populate(${_ARGS_LIBRARY_NAME}) + add_subdirectory( + ${${_ARGS_LIBRARY_NAME}_SOURCE_DIR} ${${_ARGS_LIBRARY_NAME}_BINARY_DIR} + EXCLUDE_FROM_ALL + ) + endif() + else() + FetchContent_MakeAvailable(${_ARGS_LIBRARY_NAME}) + endif() + message(CHECK_PASS "Done") + endif() + else() + message(CHECK_PASS "found") + endif() +endmacro() diff --git a/simulate/cmake/MujocoHarden.cmake b/simulate/cmake/MujocoHarden.cmake new file mode 100644 index 00000000..7beb88fe --- /dev/null +++ b/simulate/cmake/MujocoHarden.cmake @@ -0,0 +1,35 @@ +# Copyright 2022 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. + +option(MUJOCO_HARDEN "Enable build hardening for MuJoCo." OFF) +if(MUJOCO_HARDEN + AND NOT + CMAKE_CXX_COMPILER_ID + MATCHES + ".*Clang.*" +) + message(FATAL_ERROR "MUJOCO_HARDEN is only supported when building with Clang") +endif() + +if(MUJOCO_HARDEN) + set(MUJOCO_HARDEN_COMPILE_OPTIONS -D_FORTIFY_SOURCE=2 -fstack-protector) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-bind_at_load) + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + set(MUJOCO_HARDEN_LINK_OPTIONS -Wl,-z,relro -Wl,-z,now) + endif() +else() + set(MUJOCO_HARDEN_COMPILE_OPTIONS "") + set(MUJOCO_HARDEN_LINK_OPTIONS "") +endif() diff --git a/simulate/cmake/MujocoLinkOptions.cmake b/simulate/cmake/MujocoLinkOptions.cmake new file mode 100644 index 00000000..242767f9 --- /dev/null +++ b/simulate/cmake/MujocoLinkOptions.cmake @@ -0,0 +1,67 @@ +# Copyright 2021 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. + +include(CheckCSourceCompiles) + +# Gets the appropriate linker options for building MuJoCo, based on features available on the +# linker. +function(get_mujoco_extra_link_options OUTPUT_VAR) + if(MSVC) + set(EXTRA_LINK_OPTIONS /OPT:REF /OPT:ICF=5) + else() + set(EXTRA_LINK_OPTIONS) + + if(WIN32) + set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld-link") + check_c_source_compiles("int main() {}" SUPPORTS_LLD) + if(SUPPORTS_LLD) + set(EXTRA_LINK_OPTIONS + ${EXTRA_LINK_OPTIONS} + -fuse-ld=lld-link + -Wl,/OPT:REF + -Wl,/OPT:ICF + ) + endif() + else() + set(CMAKE_REQUIRED_FLAGS "-fuse-ld=lld") + check_c_source_compiles("int main() {}" SUPPORTS_LLD) + if(SUPPORTS_LLD) + set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=lld) + else() + set(CMAKE_REQUIRED_FLAGS "-fuse-ld=gold") + check_c_source_compiles("int main() {}" SUPPORTS_GOLD) + if(SUPPORTS_GOLD) + set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -fuse-ld=gold) + endif() + endif() + + set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,--gc-sections") + check_c_source_compiles("int main() {}" SUPPORTS_GC_SECTIONS) + if(SUPPORTS_GC_SECTIONS) + set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,--gc-sections) + else() + set(CMAKE_REQUIRED_FLAGS ${EXTRA_LINK_OPTIONS} "-Wl,-dead_strip") + check_c_source_compiles("int main() {}" SUPPORTS_DEAD_STRIP) + if(SUPPORTS_DEAD_STRIP) + set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} -Wl,-dead_strip) + endif() + endif() + endif() + endif() + + set("${OUTPUT_VAR}" + ${EXTRA_LINK_OPTIONS} + PARENT_SCOPE + ) +endfunction() diff --git a/simulate/cmake/MujocoMacOS.cmake b/simulate/cmake/MujocoMacOS.cmake new file mode 100644 index 00000000..d2f378f6 --- /dev/null +++ b/simulate/cmake/MujocoMacOS.cmake @@ -0,0 +1,38 @@ +# Copyright 2022 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. + +if(APPLE) + # 10.12 is the oldest version of macOS that supports C++17, launched 2016. + set(MUJOCO_MACOSX_VERSION_MIN 10.12) + + # We are setting the -mmacosx-version-min compiler flag directly rather than using the + # CMAKE_OSX_DEPLOYMENT_TARGET variable since we do not want to affect choice of SDK, + # and also we only want to apply the version restriction locally. + set(MUJOCO_MACOS_COMPILE_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN} + -Werror=partial-availability -Werror=unguarded-availability + ) + set(MUJOCO_MACOS_LINK_OPTIONS -mmacosx-version-min=${MUJOCO_MACOSX_VERSION_MIN} + -Wl,-no_weak_imports + ) +else() + set(MUJOCO_MACOS_COMPILE_OPTIONS "") + set(MUJOCO_MACOS_LINK_OPTIONS "") +endif() + +function(enforce_mujoco_macosx_min_version) + if(APPLE) + add_compile_options(${MUJOCO_MACOS_COMPILE_OPTIONS}) + add_link_options(${MUJOCO_MACOS_LINK_OPTIONS}) + endif() +endfunction() diff --git a/simulate/cmake/SimulateDependencies.cmake b/simulate/cmake/SimulateDependencies.cmake new file mode 100644 index 00000000..3821cc73 --- /dev/null +++ b/simulate/cmake/SimulateDependencies.cmake @@ -0,0 +1,102 @@ +# Copyright 2021 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. + +include(FindOrFetch) + +if(SIMULATE_STANDALONE) + # If standalone, by default look for MuJoCo binary version. + set(DEFAULT_USE_SYSTEM_MUJOCO ON) +else() + set(DEFAULT_USE_SYSTEM_MUJOCO OFF) +endif() + +option(MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO "Use installed MuJoCo version." + ${DEFAULT_USE_SYSTEM_MUJOCO} +) +unset(DEFAULT_USE_SYSTEM_MUJOCO) + +option(MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO "Use installed MuJoCo version." OFF) +option(MUJOCO_SIMULATE_USE_SYSTEM_GLFW "Use installed GLFW version." OFF) + +set(MUJOCO_DEP_VERSION_glfw + 7d5a16ce714f0b5f4efa3262de22e4d948851525 # 3.3.6 + CACHE STRING "Version of `glfw` to be fetched." +) +mark_as_advanced(MUJOCO_DEP_VERSION_glfw) + +find_package(Threads REQUIRED) + +set(MUJOCO_BUILD_EXAMPLES OFF) +set(MUJOCO_BUILD_TESTS OFF) +set(MUJOCO_BUILD_PYTHON OFF) +set(MUJOCO_TEST_PYTHON_UTIL OFF) + +findorfetch( + USE_SYSTEM_PACKAGE + MUJOCO_SIMULATE_USE_SYSTEM_MUJOCO + PACKAGE_NAME + mujoco + LIBRARY_NAME + mujoco + GIT_REPO + https://github.com/deepmind/mujoco.git + GIT_TAG + main + TARGETS + mujoco + EXCLUDE_FROM_ALL +) + +option(MUJOCO_SIMULATE_STATIC_GLFW "Link MuJoCo simulate library and app against GLFW statically." ON) +if(MUJOCO_SIMULATE_STATIC_GLFW) + set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS + OFF + CACHE INTERNAL "Build SHARED libraries" + ) +endif() + +set(GLFW_BUILD_EXAMPLES OFF) +set(GLFW_BUILD_TESTS OFF) +set(GLFW_BUILD_DOCS OFF) +set(GLFW_INSTALL OFF) + +findorfetch( + USE_SYSTEM_PACKAGE + MUJOCO_SAMPLES_USE_SYSTEM_GLFW + PACKAGE_NAME + glfw + LIBRARY_NAME + glfw + GIT_REPO + https://github.com/glfw/glfw.git + GIT_TAG + ${MUJOCO_DEP_VERSION_glfw} + TARGETS + glfw + EXCLUDE_FROM_ALL +) + +if(MUJOCO_SIMULATE_STATIC_GLFW) + set(BUILD_SHARED_LIBS + ${BUILD_SHARED_LIBS_OLD} + CACHE BOOL "Build SHARED libraries" FORCE + ) + unset(BUILD_SHARED_LIBS_OLD) +endif() + +if(NOT SIMULATE_STANDALONE) + target_compile_options(glfw PRIVATE ${MUJOCO_MACOS_COMPILE_OPTIONS}) + target_link_options(glfw PRIVATE ${MUJOCO_MACOS_LINK_OPTIONS}) +endif() diff --git a/simulate/cmake/SimulateOptions.cmake b/simulate/cmake/SimulateOptions.cmake new file mode 100644 index 00000000..2b0ce938 --- /dev/null +++ b/simulate/cmake/SimulateOptions.cmake @@ -0,0 +1,106 @@ +# Copyright 2021 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. + +# Global compilation settings +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # For LLVM tooling + +if(NOT CMAKE_CONFIGURATION_TYPES) + if(NOT CMAKE_BUILD_TYPE) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE + "Release" + CACHE STRING "Choose the type of build, recommanded options are: Debug or Release" FORCE + ) + endif() + set(BUILD_TYPES + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo" + ) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${BUILD_TYPES}) +endif() + +include(GNUInstallDirs) + +# Change the default output directory in the build structure. This is not stricly needed, but helps +# running in Windows, such that all built executables have DLLs in the same folder as the .exe +# files. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + +set(OpenGL_GL_PREFERENCE GLVND) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) + +if(MSVC) + add_compile_options(/Gy /Gw /Oi) +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-fdata-sections -ffunction-sections) +endif() + +# We default to shared library. +set(BUILD_SHARED_LIBS + ON + CACHE BOOL "Build Mujoco as shared library." +) + +option(MUJOCO_ENABLE_AVX "Build binaries that require AVX instructions, if possible." ON) +option(MUJOCO_ENABLE_AVX_INTRINSICS "Make use of hand-written AVX intrinsics, if possible." ON) +option(MUJOCO_ENABLE_RPATH "Enable RPath support when installing Mujoco." ON) +mark_as_advanced(MUJOCO_ENABLE_RPATH) + +if(MUJOCO_ENABLE_AVX) + include(CheckAvxSupport) + get_avx_compile_options(AVX_COMPILE_OPTIONS) +else() + set(AVX_COMPILE_OPTIONS) +endif() + +option(MUJOCO_BUILD_MACOS_FRAMEWORKS "Build libraries as macOS Frameworks" OFF) + +# Get some extra link options. +include(MujocoLinkOptions) +get_mujoco_extra_link_options(EXTRA_LINK_OPTIONS) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT MSVC)) + set(EXTRA_COMPILE_OPTIONS -Wall -Werror) + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(EXTRA_COMPILE_OPTIONS + -Wno-int-in-bool-context + -Wno-maybe-uninitialized + -Wno-sign-compare + -Wno-stringop-overflow + -Wno-stringop-truncation + ) + endif() +endif() + +if(WIN32) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) +endif() + +include(MujocoHarden) +set(EXTRA_COMPILE_OPTIONS ${EXTRA_COMPILE_OPTIONS} ${MUJOCO_HARDEN_COMPILE_OPTIONS}) +set(EXTRA_LINK_OPTIONS ${EXTRA_LINK_OPTIONS} ${MUJOCO_HARDEN_LINK_OPTIONS}) diff --git a/simulate/main.cc b/simulate/main.cc index 6e61188b..34e8f263 100644 --- a/simulate/main.cc +++ b/simulate/main.cc @@ -19,7 +19,7 @@ #include #include -#include +#include #include "uitools.h" #include "simulate.h" diff --git a/simulate/simulate.cc b/simulate/simulate.cc index 77fcecf3..1ad4d525 100644 --- a/simulate/simulate.cc +++ b/simulate/simulate.cc @@ -521,7 +521,7 @@ void makephysics(mj::Simulate* simulate, int oldstate) { mjuiDef defPhysics[] = { {mjITEM_SECTION, "Physics", oldstate, nullptr, "AP"}, - {mjITEM_SELECT, "Integrator", 2, &(m->opt.integrator), "Euler\nRK4\nimplicit"}, + {mjITEM_SELECT, "Integrator", 2, &(simulate->m->opt.integrator), "Euler\nRK4\nimplicit"}, {mjITEM_SELECT, "Collision", 2, &(simulate->m->opt.collision), "All\nPair\nDynamic"}, {mjITEM_SELECT, "Cone", 2, &(simulate->m->opt.cone), "Pyramidal\nElliptic"}, {mjITEM_SELECT, "Jacobian", 2, &(simulate->m->opt.jacobian), "Dense\nSparse\nAuto"}, @@ -1058,7 +1058,7 @@ void uiEvent(mjuiState* state) { case 0: // Save xml { const std::string path = getSavePath("mjmodel.xml"); - if (!path.empty() && !mj_saveLastXML(path.c_str(), m, err, 200)) { + if (!path.empty() && !mj_saveLastXML(path.c_str(), simulate->m, err, 200)) { std::printf("Save XML error: %s", err); } } @@ -1068,7 +1068,7 @@ void uiEvent(mjuiState* state) { { const std::string path = getSavePath("mjmodel.mjb"); if (!path.empty()) { - mj_saveModel(m, path.c_str(), NULL, 0); + mj_saveModel(simulate->m, path.c_str(), NULL, 0); } } break;