Add .cmake files and fix LICENSE file path in make_sdist.sh.

Also make minor modifications to Python bindings code for GCC compatibility.

Fixes #191.

PiperOrigin-RevId: 435127640
Change-Id: I8bd3a35bbb2724a24341072ba8df3da4372f83d3
This commit is contained in:
Saran Tunyasuvunakool
2022-03-16 12:39:08 -07:00
parent 5aba2c9fc6
commit b7b7af06d9
7 changed files with 311 additions and 2 deletions
+53
View File
@@ -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 <immintrin.h>
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()
+128
View File
@@ -0,0 +1,128 @@
# 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 from a git
# repository (OFF).
# - ``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``.
# - ``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.
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)
foreach(target ${_ARGS_TARGETS})
if(NOT TARGET ${target})
message(STATUS "mujoco::FindOrFetch: 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(
STATUS
"mujoco::FindOrFetch: Attempting to find `${_ARGS_PACKAGE_NAME}` in system packages..."
)
find_package(${_ARGS_PACKAGE_NAME} REQUIRED)
message(STATUS "mujoco::FindOrFetch: Found `${_ARGS_PACKAGE_NAME}` in system packages.")
else()
message(
STATUS
"mujoco::FindOrFetch: Attempting to fetch `${_ARGS_LIBRARY_NAME}` from `${_ARGS_GIT_REPO}`..."
)
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(
STATUS "mujoco::FindOrFetch: Fetched `${_ARGS_LIBRARY_NAME}` from `${_ARGS_GIT_REPO}`."
)
endif()
else()
message(STATUS "mujoco::FindOrFetch: `${_ARGS_PACKAGE_NAME}` targets found.")
endif()
endmacro()
+67
View File
@@ -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()
+52
View File
@@ -0,0 +1,52 @@
# 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.
function(add_mujoco_shell_test TEST_NAME TARGET_BINARY)
find_program(BASH_PROGRAM bash)
if(BASH_PROGRAM)
# Set up the test directory
set(TEST_TMPDIR "${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME}")
add_test(NAME ${TEST_NAME}_setup
COMMAND ${BASH_PROGRAM} "${PROJECT_SOURCE_DIR}/cmake/setup_test_dir.sh" ${TEST_TMPDIR}
)
set_tests_properties(${TEST_NAME}_setup PROPERTIES FIXTURES_SETUP ${TEST_NAME}_fixture)
add_test(NAME ${TEST_NAME}_cleanup
COMMAND ${BASH_PROGRAM} "${PROJECT_SOURCE_DIR}/cmake/cleanup_test_dir.sh"
${TEST_TMPDIR}
)
set_tests_properties(${TEST_NAME}_cleanup PROPERTIES FIXTURES_CLEANUP ${TEST_NAME}_fixture)
add_test(
NAME ${TEST_NAME}
COMMAND ${BASH_PROGRAM} "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_NAME}.sh"
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TARGET_BINARY}>
)
set_tests_properties(${TEST_NAME} PROPERTIES FIXTURES_REQUIRED ${TEST_NAME}_fixture)
set_property(
TEST "${TEST_NAME}"
PROPERTY ENVIRONMENT
"CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}"
"TARGET_BINARY=$<TARGET_FILE:${TARGET_BINARY}>"
"TEST_TMPDIR=${TEST_TMPDIR}"
)
if(WIN32)
# Define the directory containing the mujoco DLL library so that it can be added to the PATH.
# We modify the PATH in the script as it is more reliable.
set_property(
TEST "${TEST_NAME}"
APPEND
PROPERTY ENVIRONMENT "MUJOCO_DLL_DIR=$<TARGET_FILE_DIR:mujoco_nogl>"
)
endif()
endif()
endfunction()
+2 -2
View File
@@ -47,11 +47,11 @@ python "${package_dir}"/mujoco/codegen/generate_function_traits.py > \
export PYTHONPATH="${old_pythonpath}"
# Copy over the LICENSE file.
cp "${package_dir}"/../../LICENSE .
cp "${package_dir}"/../LICENSE .
# Copy over CMake scripts.
mkdir cmake
cp "${package_dir}"/../../cmake/*.cmake cmake
cp "${package_dir}"/../cmake/*.cmake cmake
python setup.py sdist --formats=gztar
tar -tf dist/mujoco-*.tar.gz
+5
View File
@@ -119,7 +119,12 @@ struct MjErrorIntercepter {
template <typename Return, typename... Args, typename Callable>
MUJOCO_ALWAYS_INLINE
static constexpr auto WrapFunc(Callable&& callable) {
#if defined(__GNUC__) && !defined(__clang__)
// GCC can't inline functions that call setjmp
return [callable](Args... args) mutable {
#else
return [callable](Args... args) MUJOCO_ALWAYS_INLINE_LAMBDA_MUTABLE {
#endif
_mjPRIVATE__set_tls_error_fn(&MjErrorHandler);
// DON'T MIX RAII WITH SETJMP!
+4
View File
@@ -25,7 +25,11 @@
(defined(__GNUC__) && !defined(__clang__))
#define MUJOCO_ALWAYS_INLINE __attribute__((always_inline))
#define MUJOCO_ALWAYS_INLINE_LAMBDA MUJOCO_ALWAYS_INLINE
#if defined(__clang__)
#define MUJOCO_ALWAYS_INLINE_LAMBDA_MUTABLE MUJOCO_ALWAYS_INLINE_LAMBDA mutable
#else
#define MUJOCO_ALWAYS_INLINE_LAMBDA_MUTABLE mutable MUJOCO_ALWAYS_INLINE_LAMBDA
#endif
#elif defined(_MSC_VER)
#define MUJOCO_ALWAYS_INLINE __forceinline
#if _MSC_VER >= 1927 && _MSVC_LANG >= 202002L