FindOrFetch.cmake 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # Copyright 2021 DeepMind Technologies Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # https://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. #
  15. #.rst:
  16. # FindOrFetch
  17. # ----------------------
  18. #
  19. # Find or fetch a package in order to satisfy target dependencies.
  20. #
  21. # FindOrFetch([USE_SYSTEM_PACKAGE [ON/OFF]]
  22. # [PACKAGE_NAME [name]]
  23. # [LIBRARY_NAME [name]]
  24. # [GIT_REPO [repo]]
  25. # [GIT_TAG [tag]]
  26. # [PATCH_COMMAND [cmd] [args]]
  27. # [TARGETS [targets]]
  28. # [EXCLUDE_FROM_ALL])
  29. #
  30. # The command has the following parameters:
  31. #
  32. # Arguments:
  33. # - ``USE_SYSTEM_PACKAGE`` one-value argument on whether to search for the
  34. # package in the system (ON) or whether to fetch the library using
  35. # FetchContent from the specified Git repository (OFF). Note that
  36. # FetchContent variables will override this behaviour.
  37. # - ``PACKAGE_NAME`` name of the system-package. Ignored if
  38. # ``USE_SYSTEM_PACKAGE`` is ``OFF``.
  39. # - ``LIBRARY_NAME`` name of the library. Ignored if
  40. # ``USE_SYSTEM_PACKAGE`` is ``ON``.
  41. # - ``GIT_REPO`` git repository to fetch the library from. Ignored if
  42. # ``USE_SYSTEM_PACKAGE`` is ``ON``.
  43. # - ``GIT_TAG`` tag reference when fetching the library from the git
  44. # repository. Ignored if ``USE_SYSTEM_PACKAGE`` is ``ON``.
  45. # - ``PATCH_COMMAND`` Specifies a custom command to patch the sources after an
  46. # update. See https://cmake.org/cmake/help/latest/module/ExternalProject.html#command:externalproject_add
  47. # for details on the parameter.
  48. # - ``TARGETS`` list of targets to be satisfied. If any of these targets are
  49. # not currently defined, this macro will attempt to either find or fetch the
  50. # package.
  51. # - ``EXCLUDE_FROM_ALL`` if specified, the targets are not added to the ``all``
  52. # metatarget.
  53. #
  54. # Note: if ``USE_SYSTEM_PACKAGE`` is ``OFF``, FetchContent will be used to
  55. # retrieve the specified targets. It is possible to specify any variable in
  56. # https://cmake.org/cmake/help/latest/module/FetchContent.html#variables to
  57. # override this macro behaviour.
  58. if(COMMAND FindOrFetch)
  59. return()
  60. endif()
  61. macro(FindOrFetch)
  62. if(NOT FetchContent)
  63. include(FetchContent)
  64. endif()
  65. # Parse arguments.
  66. set(options EXCLUDE_FROM_ALL)
  67. set(one_value_args
  68. USE_SYSTEM_PACKAGE
  69. PACKAGE_NAME
  70. LIBRARY_NAME
  71. GIT_REPO
  72. GIT_TAG
  73. )
  74. set(multi_value_args PATCH_COMMAND TARGETS)
  75. cmake_parse_arguments(
  76. _ARGS
  77. "${options}"
  78. "${one_value_args}"
  79. "${multi_value_args}"
  80. ${ARGN}
  81. )
  82. # Check if all targets are found.
  83. if(NOT _ARGS_TARGETS)
  84. message(FATAL_ERROR "mujoco::FindOrFetch: TARGETS must be specified.")
  85. endif()
  86. set(targets_found TRUE)
  87. message(CHECK_START
  88. "mujoco::FindOrFetch: checking for targets in package `${_ARGS_PACKAGE_NAME}`"
  89. )
  90. foreach(target ${_ARGS_TARGETS})
  91. if(NOT TARGET ${target})
  92. message(CHECK_FAIL "target `${target}` not defined.")
  93. set(targets_found FALSE)
  94. break()
  95. endif()
  96. endforeach()
  97. # If targets are not found, use `find_package` or `FetchContent...` to get it.
  98. if(NOT targets_found)
  99. if(${_ARGS_USE_SYSTEM_PACKAGE})
  100. message(CHECK_START
  101. "mujoco::FindOrFetch: finding `${_ARGS_PACKAGE_NAME}` in system packages..."
  102. )
  103. find_package(${_ARGS_PACKAGE_NAME} REQUIRED)
  104. message(CHECK_PASS "found")
  105. else()
  106. message(CHECK_START
  107. "mujoco::FindOrFetch: Using FetchContent to retrieve `${_ARGS_LIBRARY_NAME}`"
  108. )
  109. FetchContent_Declare(
  110. ${_ARGS_LIBRARY_NAME}
  111. GIT_REPOSITORY ${_ARGS_GIT_REPO}
  112. GIT_TAG ${_ARGS_GIT_TAG}
  113. GIT_SHALLOW FALSE
  114. PATCH_COMMAND ${_ARGS_PATCH_COMMAND}
  115. UPDATE_DISCONNECTED TRUE
  116. )
  117. if(${_ARGS_EXCLUDE_FROM_ALL})
  118. FetchContent_GetProperties(${_ARGS_LIBRARY_NAME})
  119. if(NOT ${${_ARGS_LIBRARY_NAME}_POPULATED})
  120. FetchContent_Populate(${_ARGS_LIBRARY_NAME})
  121. add_subdirectory(
  122. ${${_ARGS_LIBRARY_NAME}_SOURCE_DIR} ${${_ARGS_LIBRARY_NAME}_BINARY_DIR}
  123. EXCLUDE_FROM_ALL
  124. )
  125. endif()
  126. else()
  127. FetchContent_MakeAvailable(${_ARGS_LIBRARY_NAME})
  128. endif()
  129. message(CHECK_PASS "Done")
  130. endif()
  131. else()
  132. message(CHECK_PASS "found")
  133. endif()
  134. endmacro()