FindPackageHandleStandardArgs.cmake 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #[=======================================================================[.rst:
  2. FindPackageHandleStandardArgs
  3. -----------------------------
  4. This module provides a function intended to be used in :ref:`Find Modules`
  5. implementing :command:`find_package(<PackageName>)` calls. It handles the
  6. ``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``.
  7. It also sets the ``<PackageName>_FOUND`` variable. The package is
  8. considered found if all variables listed contain valid results, e.g.
  9. valid filepaths.
  10. .. command:: find_package_handle_standard_args
  11. There are two signatures::
  12. find_package_handle_standard_args(<PackageName>
  13. (DEFAULT_MSG|<custom-failure-message>)
  14. <required-var>...
  15. )
  16. find_package_handle_standard_args(<PackageName>
  17. [FOUND_VAR <result-var>]
  18. [REQUIRED_VARS <required-var>...]
  19. [VERSION_VAR <version-var>]
  20. [HANDLE_COMPONENTS]
  21. [CONFIG_MODE]
  22. [FAIL_MESSAGE <custom-failure-message>]
  23. )
  24. The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
  25. the variables ``<required-var>...`` are valid and any optional
  26. constraints are satisfied, and ``FALSE`` otherwise. A success or
  27. failure message may be displayed based on the results and on
  28. whether the ``REQUIRED`` and/or ``QUIET`` option was given to
  29. the :command:`find_package` call.
  30. The options are:
  31. ``(DEFAULT_MSG|<custom-failure-message>)``
  32. In the simple signature this specifies the failure message.
  33. Use ``DEFAULT_MSG`` to ask for a default message to be computed
  34. (recommended). Not valid in the full signature.
  35. ``FOUND_VAR <result-var>``
  36. Obsolete. Specifies either ``<PackageName>_FOUND`` or
  37. ``<PACKAGENAME>_FOUND`` as the result variable. This exists only
  38. for compatibility with older versions of CMake and is now ignored.
  39. Result variables of both names are always set for compatibility.
  40. ``REQUIRED_VARS <required-var>...``
  41. Specify the variables which are required for this package.
  42. These may be named in the generated failure message asking the
  43. user to set the missing variable values. Therefore these should
  44. typically be cache entries such as ``FOO_LIBRARY`` and not output
  45. variables like ``FOO_LIBRARIES``.
  46. ``VERSION_VAR <version-var>``
  47. Specify the name of a variable that holds the version of the package
  48. that has been found. This version will be checked against the
  49. (potentially) specified required version given to the
  50. :command:`find_package` call, including its ``EXACT`` option.
  51. The default messages include information about the required
  52. version and the version which has been actually found, both
  53. if the version is ok or not.
  54. ``HANDLE_COMPONENTS``
  55. Enable handling of package components. In this case, the command
  56. will report which components have been found and which are missing,
  57. and the ``<PackageName>_FOUND`` variable will be set to ``FALSE``
  58. if any of the required components (i.e. not the ones listed after
  59. the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are
  60. missing.
  61. ``CONFIG_MODE``
  62. Specify that the calling find module is a wrapper around a
  63. call to ``find_package(<PackageName> NO_MODULE)``. This implies
  64. a ``VERSION_VAR`` value of ``<PackageName>_VERSION``. The command
  65. will automatically check whether the package configuration file
  66. was found.
  67. ``FAIL_MESSAGE <custom-failure-message>``
  68. Specify a custom failure message instead of using the default
  69. generated message. Not recommended.
  70. Example for the simple signature:
  71. .. code-block:: cmake
  72. find_package_handle_standard_args(LibXml2 DEFAULT_MSG
  73. LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
  74. The ``LibXml2`` package is considered to be found if both
  75. ``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
  76. Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found
  77. and ``REQUIRED`` was used, it fails with a
  78. :command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
  79. used or not. If it is found, success will be reported, including
  80. the content of the first ``<required-var>``. On repeated CMake runs,
  81. the same message will not be printed again.
  82. Example for the full signature:
  83. .. code-block:: cmake
  84. find_package_handle_standard_args(LibArchive
  85. REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
  86. VERSION_VAR LibArchive_VERSION)
  87. In this case, the ``LibArchive`` package is considered to be found if
  88. both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
  89. Also the version of ``LibArchive`` will be checked by using the version
  90. contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given,
  91. the default messages will be printed.
  92. Another example for the full signature:
  93. .. code-block:: cmake
  94. find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
  95. find_package_handle_standard_args(Automoc4 CONFIG_MODE)
  96. In this case, a ``FindAutmoc4.cmake`` module wraps a call to
  97. ``find_package(Automoc4 NO_MODULE)`` and adds an additional search
  98. directory for ``automoc4``. Then the call to
  99. ``find_package_handle_standard_args`` produces a proper success/failure
  100. message.
  101. #]=======================================================================]
  102. #=============================================================================
  103. # Copyright 2007-2009 Kitware, Inc.
  104. #
  105. # Distributed under the OSI-approved BSD License (the "License");
  106. # see accompanying file Copyright.txt for details.
  107. #
  108. # This software is distributed WITHOUT ANY WARRANTY; without even the
  109. # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  110. # See the License for more information.
  111. #=============================================================================
  112. # (To distribute this file outside of CMake, substitute the full
  113. # License text for the above reference.)
  114. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
  115. include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
  116. # internal helper macro
  117. macro(_FPHSA_FAILURE_MESSAGE _msg)
  118. if (${_NAME}_FIND_REQUIRED)
  119. message(FATAL_ERROR "${_msg}")
  120. else ()
  121. if (NOT ${_NAME}_FIND_QUIETLY)
  122. message(STATUS "${_msg}")
  123. endif ()
  124. endif ()
  125. endmacro()
  126. # internal helper macro to generate the failure message when used in CONFIG_MODE:
  127. macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
  128. # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
  129. if(${_NAME}_CONFIG)
  130. _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
  131. else()
  132. # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
  133. # List them all in the error message:
  134. if(${_NAME}_CONSIDERED_CONFIGS)
  135. set(configsText "")
  136. list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
  137. math(EXPR configsCount "${configsCount} - 1")
  138. foreach(currentConfigIndex RANGE ${configsCount})
  139. list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
  140. list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
  141. set(configsText "${configsText} ${filename} (version ${version})\n")
  142. endforeach()
  143. if (${_NAME}_NOT_FOUND_MESSAGE)
  144. set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
  145. endif()
  146. _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
  147. else()
  148. # Simple case: No Config-file was found at all:
  149. _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
  150. endif()
  151. endif()
  152. endmacro()
  153. function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
  154. # set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
  155. # new extended or in the "old" mode:
  156. set(options CONFIG_MODE HANDLE_COMPONENTS)
  157. set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR)
  158. set(multiValueArgs REQUIRED_VARS)
  159. set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
  160. list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
  161. if(${INDEX} EQUAL -1)
  162. set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
  163. set(FPHSA_REQUIRED_VARS ${ARGN})
  164. set(FPHSA_VERSION_VAR)
  165. else()
  166. CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN})
  167. if(FPHSA_UNPARSED_ARGUMENTS)
  168. message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
  169. endif()
  170. if(NOT FPHSA_FAIL_MESSAGE)
  171. set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG")
  172. endif()
  173. endif()
  174. # now that we collected all arguments, process them
  175. if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
  176. set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
  177. endif()
  178. # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package()
  179. # when it successfully found the config-file, including version checking:
  180. if(FPHSA_CONFIG_MODE)
  181. list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
  182. list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
  183. set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
  184. endif()
  185. if(NOT FPHSA_REQUIRED_VARS)
  186. message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
  187. endif()
  188. list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
  189. string(TOUPPER ${_NAME} _NAME_UPPER)
  190. string(TOLOWER ${_NAME} _NAME_LOWER)
  191. if(FPHSA_FOUND_VAR)
  192. if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$")
  193. set(_FOUND_VAR ${FPHSA_FOUND_VAR})
  194. else()
  195. message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.")
  196. endif()
  197. else()
  198. set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
  199. endif()
  200. # collect all variables which were not found, so they can be printed, so the
  201. # user knows better what went wrong (#6375)
  202. set(MISSING_VARS "")
  203. set(DETAILS "")
  204. # check if all passed variables are valid
  205. set(FPHSA_FOUND_${_NAME} TRUE)
  206. foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
  207. if(NOT ${_CURRENT_VAR})
  208. set(FPHSA_FOUND_${_NAME} FALSE)
  209. set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}")
  210. else()
  211. set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]")
  212. endif()
  213. endforeach()
  214. if(FPHSA_FOUND_${_NAME})
  215. set(${_NAME}_FOUND TRUE)
  216. set(${_NAME_UPPER}_FOUND TRUE)
  217. else()
  218. set(${_NAME}_FOUND FALSE)
  219. set(${_NAME_UPPER}_FOUND FALSE)
  220. endif()
  221. # component handling
  222. unset(FOUND_COMPONENTS_MSG)
  223. unset(MISSING_COMPONENTS_MSG)
  224. if(FPHSA_HANDLE_COMPONENTS)
  225. foreach(comp ${${_NAME}_FIND_COMPONENTS})
  226. if(${_NAME}_${comp}_FOUND)
  227. if(NOT DEFINED FOUND_COMPONENTS_MSG)
  228. set(FOUND_COMPONENTS_MSG "found components: ")
  229. endif()
  230. set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
  231. else()
  232. if(NOT DEFINED MISSING_COMPONENTS_MSG)
  233. set(MISSING_COMPONENTS_MSG "missing components: ")
  234. endif()
  235. set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
  236. if(${_NAME}_FIND_REQUIRED_${comp})
  237. set(${_NAME}_FOUND FALSE)
  238. set(MISSING_VARS "${MISSING_VARS} ${comp}")
  239. endif()
  240. endif()
  241. endforeach()
  242. set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
  243. set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
  244. endif()
  245. # version handling:
  246. set(VERSION_MSG "")
  247. set(VERSION_OK TRUE)
  248. set(VERSION ${${FPHSA_VERSION_VAR}})
  249. # check with DEFINED here as the requested or found version may be "0"
  250. if (DEFINED ${_NAME}_FIND_VERSION)
  251. if(DEFINED ${FPHSA_VERSION_VAR})
  252. if(${_NAME}_FIND_VERSION_EXACT) # exact version required
  253. # count the dots in the version string
  254. string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
  255. # add one dot because there is one dot more than there are components
  256. string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
  257. if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
  258. # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
  259. # is at most 4 here. Therefore a simple lookup table is used.
  260. if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
  261. set(_VERSION_REGEX "[^.]*")
  262. elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
  263. set(_VERSION_REGEX "[^.]*\\.[^.]*")
  264. elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
  265. set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
  266. else ()
  267. set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
  268. endif ()
  269. string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
  270. unset(_VERSION_REGEX)
  271. if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
  272. set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
  273. set(VERSION_OK FALSE)
  274. else ()
  275. set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
  276. endif ()
  277. unset(_VERSION_HEAD)
  278. else ()
  279. if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL VERSION)
  280. set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
  281. set(VERSION_OK FALSE)
  282. else ()
  283. set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
  284. endif ()
  285. endif ()
  286. unset(_VERSION_DOTS)
  287. else() # minimum version specified:
  288. if (${_NAME}_FIND_VERSION VERSION_GREATER VERSION)
  289. set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"")
  290. set(VERSION_OK FALSE)
  291. else ()
  292. set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")")
  293. endif ()
  294. endif()
  295. else()
  296. # if the package was not found, but a version was given, add that to the output:
  297. if(${_NAME}_FIND_VERSION_EXACT)
  298. set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
  299. else()
  300. set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
  301. endif()
  302. endif()
  303. else ()
  304. if(VERSION)
  305. set(VERSION_MSG "(found version \"${VERSION}\")")
  306. endif()
  307. endif ()
  308. if(VERSION_OK)
  309. set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]")
  310. else()
  311. set(${_NAME}_FOUND FALSE)
  312. endif()
  313. # print the result:
  314. if (${_NAME}_FOUND)
  315. FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
  316. else ()
  317. if(FPHSA_CONFIG_MODE)
  318. _FPHSA_HANDLE_FAILURE_CONFIG_MODE()
  319. else()
  320. if(NOT VERSION_OK)
  321. _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})")
  322. else()
  323. _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}")
  324. endif()
  325. endif()
  326. endif ()
  327. set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
  328. set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
  329. endfunction()