# 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]] # [CUSTOM_CMAKE [path]] # [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``. # - ``CUSTOM_CMAKE`` path to a custom CMakeLists.txt file to be used 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(NOT COMMAND FindOrFetch) 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 CUSTOM_CMAKE ) 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() set(USE_LOCAL_TARBALL FALSE) if(MUJOCO_CMAKE_DEP_CACHE) # Try to find versioned library tarball. set(TARBALL_PATH "${MUJOCO_CMAKE_DEP_CACHE}/${_ARGS_LIBRARY_NAME}-${_ARGS_GIT_TAG}.tar.gz") if(EXISTS "${TARBALL_PATH}") set(USE_LOCAL_TARBALL TRUE) endif() endif() if(_ARGS_PATCH_COMMAND) set(_WRAPPED_PATCH_COMMAND ${CMAKE_COMMAND} -E env GIT_CEILING_DIRECTORIES=${CMAKE_BINARY_DIR} ${_ARGS_PATCH_COMMAND}) else() set(_WRAPPED_PATCH_COMMAND) endif() set(FETCHCONTENT_QUIET OFF) if(USE_LOCAL_TARBALL) message(STATUS "mujoco::FindOrFetch: Using package cache for ${_ARGS_LIBRARY_NAME}: ${TARBALL_PATH}") FetchContent_Declare( ${_ARGS_LIBRARY_NAME} URL ${TARBALL_PATH} PATCH_COMMAND ${_WRAPPED_PATCH_COMMAND} ) else() message(STATUS "mujoco::FindOrFetch: Using FetchContent for ${_ARGS_LIBRARY_NAME}: ${_ARGS_GIT_REPO}") FetchContent_Declare( ${_ARGS_LIBRARY_NAME} GIT_REPOSITORY ${_ARGS_GIT_REPO} GIT_TAG ${_ARGS_GIT_TAG} GIT_SHALLOW FALSE PATCH_COMMAND ${_WRAPPED_PATCH_COMMAND} UPDATE_DISCONNECTED TRUE ) endif() if(${_ARGS_EXCLUDE_FROM_ALL}) FetchContent_GetProperties(${_ARGS_LIBRARY_NAME}) if(NOT ${${_ARGS_LIBRARY_NAME}_POPULATED}) FetchContent_Populate(${_ARGS_LIBRARY_NAME}) if(NOT "${_ARGS_CUSTOM_CMAKE}" STREQUAL "") file(COPY "${_ARGS_CUSTOM_CMAKE}" DESTINATION "${${_ARGS_LIBRARY_NAME}_SOURCE_DIR}" ) endif() 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() endif() #.rst: # FetchPackage # ---------------------- # # Fetches a package from a Git repository in order to satisfy dependencies. # # FetchPackage([PACKAGE_NAME [name]] # [GIT_REPO [repo]] # [GIT_TAG [tag]] # [PATCH_COMMAND [cmd] [args]] # ) # # The command has the following parameters: # # Arguments: # - ``PACKAGE_NAME`` name of the package. # - ``GIT_REPO`` git repository to fetch the library from. # - ``GIT_TAG`` tag reference when fetching the library from the git repo. # - ``CUSTOM_CMAKE`` path to a custom CMakeLists.txt file to be used when # fetching the library from the git repository. # - ``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`` (optional) list of targets to be satisfied. If any of these # targets are not currently defined, this macro will attempt to fetch the # package. If not specified, the package name will be used as the target. # # Note: This is a wrapper around FindOrFetch that sets EXCLUDE_FROM_ALL and # USE_SYSTEM_PACKAGE to OFF. if(NOT COMMAND FetchPackage) function(FetchPackage) cmake_parse_arguments( _ARGS "EXCLUDE_FROM_ALL" "PACKAGE_NAME;GIT_REPO;GIT_TAG;CUSTOM_CMAKE" "PATCH_COMMAND;TARGETS" ${ARGN} ) if(NOT _ARGS_TARGETS) set(_ARGS_TARGETS ${_ARGS_PACKAGE_NAME}) endif() FindOrFetch( PACKAGE_NAME ${_ARGS_PACKAGE_NAME} LIBRARY_NAME ${_ARGS_PACKAGE_NAME} GIT_REPO ${_ARGS_GIT_REPO} GIT_TAG ${_ARGS_GIT_TAG} CUSTOM_CMAKE ${_ARGS_CUSTOM_CMAKE} PATCH_COMMAND ${_ARGS_PATCH_COMMAND} TARGETS ${_ARGS_TARGETS} USE_SYSTEM_PACKAGE OFF EXCLUDE_FROM_ALL ) endfunction() endif()