1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5FindPackageHandleStandardArgs
6-----------------------------
7
8This module provides functions intended to be used in :ref:`Find Modules`
9implementing :command:`find_package(<PackageName>)` calls.
10
11.. command:: find_package_handle_standard_args
12
13  This command handles the ``REQUIRED``, ``QUIET`` and version-related
14  arguments of :command:`find_package`.  It also sets the
15  ``<PackageName>_FOUND`` variable.  The package is considered found if all
16  variables listed contain valid results, e.g. valid filepaths.
17
18  There are two signatures:
19
20  .. code-block:: cmake
21
22    find_package_handle_standard_args(<PackageName>
23      (DEFAULT_MSG|<custom-failure-message>)
24      <required-var>...
25      )
26
27    find_package_handle_standard_args(<PackageName>
28      [FOUND_VAR <result-var>]
29      [REQUIRED_VARS <required-var>...]
30      [VERSION_VAR <version-var>]
31      [HANDLE_VERSION_RANGE]
32      [HANDLE_COMPONENTS]
33      [CONFIG_MODE]
34      [NAME_MISMATCHED]
35      [REASON_FAILURE_MESSAGE <reason-failure-message>]
36      [FAIL_MESSAGE <custom-failure-message>]
37      )
38
39  The ``<PackageName>_FOUND`` variable will be set to ``TRUE`` if all
40  the variables ``<required-var>...`` are valid and any optional
41  constraints are satisfied, and ``FALSE`` otherwise.  A success or
42  failure message may be displayed based on the results and on
43  whether the ``REQUIRED`` and/or ``QUIET`` option was given to
44  the :command:`find_package` call.
45
46  The options are:
47
48  ``(DEFAULT_MSG|<custom-failure-message>)``
49    In the simple signature this specifies the failure message.
50    Use ``DEFAULT_MSG`` to ask for a default message to be computed
51    (recommended).  Not valid in the full signature.
52
53  ``FOUND_VAR <result-var>``
54    .. deprecated:: 3.3
55
56    Specifies either ``<PackageName>_FOUND`` or
57    ``<PACKAGENAME>_FOUND`` as the result variable.  This exists only
58    for compatibility with older versions of CMake and is now ignored.
59    Result variables of both names are always set for compatibility.
60
61  ``REQUIRED_VARS <required-var>...``
62    Specify the variables which are required for this package.
63    These may be named in the generated failure message asking the
64    user to set the missing variable values.  Therefore these should
65    typically be cache entries such as ``FOO_LIBRARY`` and not output
66    variables like ``FOO_LIBRARIES``.
67
68    .. versionchanged:: 3.18
69      If ``HANDLE_COMPONENTS`` is specified, this option can be omitted.
70
71  ``VERSION_VAR <version-var>``
72    Specify the name of a variable that holds the version of the package
73    that has been found.  This version will be checked against the
74    (potentially) specified required version given to the
75    :command:`find_package` call, including its ``EXACT`` option.
76    The default messages include information about the required
77    version and the version which has been actually found, both
78    if the version is ok or not.
79
80  ``HANDLE_VERSION_RANGE``
81    .. versionadded:: 3.19
82
83    Enable handling of a version range, if one is specified. Without this
84    option, a developer warning will be displayed if a version range is
85    specified.
86
87  ``HANDLE_COMPONENTS``
88    Enable handling of package components.  In this case, the command
89    will report which components have been found and which are missing,
90    and the ``<PackageName>_FOUND`` variable will be set to ``FALSE``
91    if any of the required components (i.e. not the ones listed after
92    the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are
93    missing.
94
95  ``CONFIG_MODE``
96    Specify that the calling find module is a wrapper around a
97    call to ``find_package(<PackageName> NO_MODULE)``.  This implies
98    a ``VERSION_VAR`` value of ``<PackageName>_VERSION``.  The command
99    will automatically check whether the package configuration file
100    was found.
101
102  ``REASON_FAILURE_MESSAGE <reason-failure-message>``
103    .. versionadded:: 3.16
104
105    Specify a custom message of the reason for the failure which will be
106    appended to the default generated message.
107
108  ``FAIL_MESSAGE <custom-failure-message>``
109    Specify a custom failure message instead of using the default
110    generated message.  Not recommended.
111
112  ``NAME_MISMATCHED``
113    .. versionadded:: 3.17
114
115    Indicate that the ``<PackageName>`` does not match
116    ``${CMAKE_FIND_PACKAGE_NAME}``. This is usually a mistake and raises a
117    warning, but it may be intentional for usage of the command for components
118    of a larger package.
119
120Example for the simple signature:
121
122.. code-block:: cmake
123
124  find_package_handle_standard_args(LibXml2 DEFAULT_MSG
125    LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
126
127The ``LibXml2`` package is considered to be found if both
128``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid.
129Then also ``LibXml2_FOUND`` is set to ``TRUE``.  If it is not found
130and ``REQUIRED`` was used, it fails with a
131:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was
132used or not.  If it is found, success will be reported, including
133the content of the first ``<required-var>``.  On repeated CMake runs,
134the same message will not be printed again.
135
136.. note::
137
138  If ``<PackageName>`` does not match ``CMAKE_FIND_PACKAGE_NAME`` for the
139  calling module, a warning that there is a mismatch is given. The
140  ``FPHSA_NAME_MISMATCHED`` variable may be set to bypass the warning if using
141  the old signature and the ``NAME_MISMATCHED`` argument using the new
142  signature. To avoid forcing the caller to require newer versions of CMake for
143  usage, the variable's value will be used if defined when the
144  ``NAME_MISMATCHED`` argument is not passed for the new signature (but using
145  both is an error)..
146
147Example for the full signature:
148
149.. code-block:: cmake
150
151  find_package_handle_standard_args(LibArchive
152    REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR
153    VERSION_VAR LibArchive_VERSION)
154
155In this case, the ``LibArchive`` package is considered to be found if
156both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid.
157Also the version of ``LibArchive`` will be checked by using the version
158contained in ``LibArchive_VERSION``.  Since no ``FAIL_MESSAGE`` is given,
159the default messages will be printed.
160
161Another example for the full signature:
162
163.. code-block:: cmake
164
165  find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4)
166  find_package_handle_standard_args(Automoc4  CONFIG_MODE)
167
168In this case, a ``FindAutmoc4.cmake`` module wraps a call to
169``find_package(Automoc4 NO_MODULE)`` and adds an additional search
170directory for ``automoc4``.  Then the call to
171``find_package_handle_standard_args`` produces a proper success/failure
172message.
173
174.. command:: find_package_check_version
175
176  .. versionadded:: 3.19
177
178  Helper function which can be used to check if a ``<version>`` is valid
179  against version-related arguments of :command:`find_package`.
180
181  .. code-block:: cmake
182
183    find_package_check_version(<version> <result-var>
184      [HANDLE_VERSION_RANGE]
185      [RESULT_MESSAGE_VARIABLE <message-var>]
186      )
187
188  The ``<result-var>`` will hold a boolean value giving the result of the check.
189
190  The options are:
191
192  ``HANDLE_VERSION_RANGE``
193    Enable handling of a version range, if one is specified. Without this
194    option, a developer warning will be displayed if a version range is
195    specified.
196
197  ``RESULT_MESSAGE_VARIABLE <message-var>``
198    Specify a variable to get back a message describing the result of the check.
199
200Example for the usage:
201
202.. code-block:: cmake
203
204  find_package_check_version(1.2.3 result HANDLE_VERSION_RANGE
205    RESULT_MESSAGE_VARIABLE reason)
206  if (result)
207    message (STATUS "${reason}")
208  else()
209    message (FATAL_ERROR "${reason}")
210  endif()
211#]=======================================================================]
212
213include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
214
215
216cmake_policy(PUSH)
217# numbers and boolean constants
218cmake_policy (SET CMP0012 NEW)
219# IN_LIST operator
220cmake_policy (SET CMP0057 NEW)
221
222
223# internal helper macro
224macro(_FPHSA_FAILURE_MESSAGE _msg)
225  set (__msg "${_msg}")
226  if (FPHSA_REASON_FAILURE_MESSAGE)
227    string(APPEND __msg "\n    Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n")
228  endif()
229  if (${_NAME}_FIND_REQUIRED)
230    message(FATAL_ERROR "${__msg}")
231  else ()
232    if (NOT ${_NAME}_FIND_QUIETLY)
233      message(STATUS "${__msg}")
234    endif ()
235  endif ()
236endmacro()
237
238
239# internal helper macro to generate the failure message when used in CONFIG_MODE:
240macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
241  # <PackageName>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found:
242  if(${_NAME}_CONFIG)
243    _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})")
244  else()
245    # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version.
246    # List them all in the error message:
247    if(${_NAME}_CONSIDERED_CONFIGS)
248      set(configsText "")
249      list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount)
250      math(EXPR configsCount "${configsCount} - 1")
251      foreach(currentConfigIndex RANGE ${configsCount})
252        list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
253        list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
254        string(APPEND configsText "\n    ${filename} (version ${version})")
255      endforeach()
256      if (${_NAME}_NOT_FOUND_MESSAGE)
257        if (FPHSA_REASON_FAILURE_MESSAGE)
258          string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n    ")
259        else()
260          set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}")
261        endif()
262      else()
263        string(APPEND configsText "\n")
264      endif()
265      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}")
266
267    else()
268      # Simple case: No Config-file was found at all:
269      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}")
270    endif()
271  endif()
272endmacro()
273
274
275function(FIND_PACKAGE_CHECK_VERSION version result)
276  cmake_parse_arguments (PARSE_ARGV 2 FPCV "HANDLE_VERSION_RANGE;NO_AUTHOR_WARNING_VERSION_RANGE" "RESULT_MESSAGE_VARIABLE" "")
277
278  if (FPCV_UNPARSED_ARGUMENTS)
279    message (FATAL_ERROR "find_package_check_version(): ${FPCV_UNPARSED_ARGUMENTS}: unexpected arguments")
280  endif()
281  if ("RESULT_MESSAGE_VARIABLE" IN_LIST FPCV_KEYWORDS_MISSING_VALUES)
282    message (FATAL_ERROR "find_package_check_version(): RESULT_MESSAGE_VARIABLE expects an argument")
283  endif()
284
285  set (${result} FALSE PARENT_SCOPE)
286  if (FPCV_RESULT_MESSAGE_VARIABLE)
287    unset (${FPCV_RESULT_MESSAGE_VARIABLE} PARENT_SCOPE)
288  endif()
289
290  if (_CMAKE_FPHSA_PACKAGE_NAME)
291    set (package "${_CMAKE_FPHSA_PACKAGE_NAME}")
292  elseif (CMAKE_FIND_PACKAGE_NAME)
293    set (package "${CMAKE_FIND_PACKAGE_NAME}")
294  else()
295    message (FATAL_ERROR "find_package_check_version(): Cannot be used outside a 'Find Module'")
296  endif()
297
298  if (NOT FPCV_NO_AUTHOR_WARNING_VERSION_RANGE
299      AND ${package}_FIND_VERSION_RANGE AND NOT FPCV_HANDLE_VERSION_RANGE)
300    message(AUTHOR_WARNING
301      "`find_package()` specify a version range but the option "
302      "HANDLE_VERSION_RANGE` is not passed to `find_package_check_version()`. "
303      "Only the lower endpoint of the range will be used.")
304  endif()
305
306
307  set (version_ok FALSE)
308  unset (version_msg)
309
310  if (FPCV_HANDLE_VERSION_RANGE AND ${package}_FIND_VERSION_RANGE)
311    if ((${package}_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE"
312          AND version VERSION_GREATER_EQUAL ${package}_FIND_VERSION_MIN)
313        AND ((${package}_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE"
314            AND version VERSION_LESS_EQUAL ${package}_FIND_VERSION_MAX)
315          OR (${package}_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE"
316            AND version VERSION_LESS ${package}_FIND_VERSION_MAX)))
317      set (version_ok TRUE)
318      set(version_msg "(found suitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\")")
319    else()
320      set(version_msg "Found unsuitable version \"${version}\", required range is \"${${package}_FIND_VERSION_RANGE}\"")
321    endif()
322  elseif (DEFINED ${package}_FIND_VERSION)
323    if(${package}_FIND_VERSION_EXACT)       # exact version required
324      # count the dots in the version string
325      string(REGEX REPLACE "[^.]" "" version_dots "${version}")
326      # add one dot because there is one dot more than there are components
327      string(LENGTH "${version_dots}." version_dots)
328      if (version_dots GREATER ${package}_FIND_VERSION_COUNT)
329        # Because of the C++ implementation of find_package() ${package}_FIND_VERSION_COUNT
330        # is at most 4 here. Therefore a simple lookup table is used.
331        if (${package}_FIND_VERSION_COUNT EQUAL 1)
332          set(version_regex "[^.]*")
333        elseif (${package}_FIND_VERSION_COUNT EQUAL 2)
334          set(version_regex "[^.]*\\.[^.]*")
335        elseif (${package}_FIND_VERSION_COUNT EQUAL 3)
336          set(version_regex "[^.]*\\.[^.]*\\.[^.]*")
337        else()
338          set(version_regex "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
339        endif()
340        string(REGEX REPLACE "^(${version_regex})\\..*" "\\1" version_head "${version}")
341        if (NOT ${package}_FIND_VERSION VERSION_EQUAL version_head)
342          set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"")
343        else ()
344          set(version_ok TRUE)
345          set(version_msg "(found suitable exact version \"${_FOUND_VERSION}\")")
346        endif ()
347      else ()
348        if (NOT ${package}_FIND_VERSION VERSION_EQUAL version)
349          set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"")
350        else ()
351          set(version_ok TRUE)
352          set(version_msg "(found suitable exact version \"${version}\")")
353        endif ()
354      endif ()
355    else()     # minimum version
356      if (${package}_FIND_VERSION VERSION_GREATER version)
357        set(version_msg "Found unsuitable version \"${version}\", but required is at least \"${${package}_FIND_VERSION}\"")
358      else()
359        set(version_ok TRUE)
360        set(version_msg "(found suitable version \"${version}\", minimum required is \"${${package}_FIND_VERSION}\")")
361      endif()
362    endif()
363  else ()
364    set(version_ok TRUE)
365    set(version_msg "(found version \"${version}\")")
366  endif()
367
368  set (${result} ${version_ok} PARENT_SCOPE)
369  if (FPCV_RESULT_MESSAGE_VARIABLE)
370    set (${FPCV_RESULT_MESSAGE_VARIABLE} "${version_msg}" PARENT_SCOPE)
371  endif()
372endfunction()
373
374
375function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
376
377  # Set up the arguments for `cmake_parse_arguments`.
378  set(options  CONFIG_MODE  HANDLE_COMPONENTS NAME_MISMATCHED HANDLE_VERSION_RANGE)
379  set(oneValueArgs  FAIL_MESSAGE  REASON_FAILURE_MESSAGE VERSION_VAR  FOUND_VAR)
380  set(multiValueArgs REQUIRED_VARS)
381
382  # Check whether we are in 'simple' or 'extended' mode:
383  set(_KEYWORDS_FOR_EXTENDED_MODE  ${options} ${oneValueArgs} ${multiValueArgs} )
384  list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX)
385
386  unset(FPHSA_NAME_MISMATCHED_override)
387  if (DEFINED FPHSA_NAME_MISMATCHED)
388    # If the variable NAME_MISMATCHED variable is set, error if it is passed as
389    # an argument. The former is for old signatures, the latter is for new
390    # signatures.
391    list(FIND ARGN "NAME_MISMATCHED" name_mismatched_idx)
392    if (NOT name_mismatched_idx EQUAL "-1")
393      message(FATAL_ERROR
394        "The `NAME_MISMATCHED` argument may only be specified by the argument or "
395        "the variable, not both.")
396    endif ()
397
398    # But use the variable if it is not an argument to avoid forcing minimum
399    # CMake version bumps for calling modules.
400    set(FPHSA_NAME_MISMATCHED_override "${FPHSA_NAME_MISMATCHED}")
401  endif ()
402
403  if(${INDEX} EQUAL -1)
404    set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG})
405    set(FPHSA_REQUIRED_VARS ${ARGN})
406    set(FPHSA_VERSION_VAR)
407  else()
408    cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${_FIRST_ARG} ${ARGN})
409
410    if(FPHSA_UNPARSED_ARGUMENTS)
411      message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"")
412    endif()
413
414    if(NOT FPHSA_FAIL_MESSAGE)
415      set(FPHSA_FAIL_MESSAGE  "DEFAULT_MSG")
416    endif()
417
418    # In config-mode, we rely on the variable <PackageName>_CONFIG, which is set by find_package()
419    # when it successfully found the config-file, including version checking:
420    if(FPHSA_CONFIG_MODE)
421      list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG)
422      list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS)
423      set(FPHSA_VERSION_VAR ${_NAME}_VERSION)
424    endif()
425
426    if(NOT FPHSA_REQUIRED_VARS AND NOT FPHSA_HANDLE_COMPONENTS)
427      message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()")
428    endif()
429  endif()
430
431  if (DEFINED FPHSA_NAME_MISMATCHED_override)
432    set(FPHSA_NAME_MISMATCHED "${FPHSA_NAME_MISMATCHED_override}")
433  endif ()
434
435  if (DEFINED CMAKE_FIND_PACKAGE_NAME
436      AND NOT FPHSA_NAME_MISMATCHED
437      AND NOT _NAME STREQUAL CMAKE_FIND_PACKAGE_NAME)
438    message(AUTHOR_WARNING
439      "The package name passed to `find_package_handle_standard_args` "
440      "(${_NAME}) does not match the name of the calling package "
441      "(${CMAKE_FIND_PACKAGE_NAME}). This can lead to problems in calling "
442      "code that expects `find_package` result variables (e.g., `_FOUND`) "
443      "to follow a certain pattern.")
444  endif ()
445
446  if (${_NAME}_FIND_VERSION_RANGE AND NOT FPHSA_HANDLE_VERSION_RANGE)
447    message(AUTHOR_WARNING
448      "`find_package()` specify a version range but the module ${_NAME} does "
449      "not support this capability. Only the lower endpoint of the range "
450      "will be used.")
451  endif()
452
453  # to propagate package name to FIND_PACKAGE_CHECK_VERSION
454  set(_CMAKE_FPHSA_PACKAGE_NAME "${_NAME}")
455
456  # now that we collected all arguments, process them
457
458  if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG")
459    set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}")
460  endif()
461
462  if (FPHSA_REQUIRED_VARS)
463    list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR)
464  endif()
465
466  string(TOUPPER ${_NAME} _NAME_UPPER)
467  string(TOLOWER ${_NAME} _NAME_LOWER)
468
469  if(FPHSA_FOUND_VAR)
470    set(_FOUND_VAR_UPPER ${_NAME_UPPER}_FOUND)
471    set(_FOUND_VAR_MIXED ${_NAME}_FOUND)
472    if(FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_MIXED  OR  FPHSA_FOUND_VAR STREQUAL _FOUND_VAR_UPPER)
473      set(_FOUND_VAR ${FPHSA_FOUND_VAR})
474    else()
475      message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_FOUND_VAR_MIXED}\" and \"${_FOUND_VAR_UPPER}\" are valid names.")
476    endif()
477  else()
478    set(_FOUND_VAR ${_NAME_UPPER}_FOUND)
479  endif()
480
481  # collect all variables which were not found, so they can be printed, so the
482  # user knows better what went wrong (#6375)
483  set(MISSING_VARS "")
484  set(DETAILS "")
485  # check if all passed variables are valid
486  set(FPHSA_FOUND_${_NAME} TRUE)
487  foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS})
488    if(NOT ${_CURRENT_VAR})
489      set(FPHSA_FOUND_${_NAME} FALSE)
490      string(APPEND MISSING_VARS " ${_CURRENT_VAR}")
491    else()
492      string(APPEND DETAILS "[${${_CURRENT_VAR}}]")
493    endif()
494  endforeach()
495  if(FPHSA_FOUND_${_NAME})
496    set(${_NAME}_FOUND TRUE)
497    set(${_NAME_UPPER}_FOUND TRUE)
498  else()
499    set(${_NAME}_FOUND FALSE)
500    set(${_NAME_UPPER}_FOUND FALSE)
501  endif()
502
503  # component handling
504  unset(FOUND_COMPONENTS_MSG)
505  unset(MISSING_COMPONENTS_MSG)
506
507  if(FPHSA_HANDLE_COMPONENTS)
508    foreach(comp ${${_NAME}_FIND_COMPONENTS})
509      if(${_NAME}_${comp}_FOUND)
510
511        if(NOT DEFINED FOUND_COMPONENTS_MSG)
512          set(FOUND_COMPONENTS_MSG "found components:")
513        endif()
514        string(APPEND FOUND_COMPONENTS_MSG " ${comp}")
515
516      else()
517
518        if(NOT DEFINED MISSING_COMPONENTS_MSG)
519          set(MISSING_COMPONENTS_MSG "missing components:")
520        endif()
521        string(APPEND MISSING_COMPONENTS_MSG " ${comp}")
522
523        if(${_NAME}_FIND_REQUIRED_${comp})
524          set(${_NAME}_FOUND FALSE)
525          string(APPEND MISSING_VARS " ${comp}")
526        endif()
527
528      endif()
529    endforeach()
530    set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
531    string(APPEND DETAILS "[c${COMPONENT_MSG}]")
532  endif()
533
534  # version handling:
535  set(VERSION_MSG "")
536  set(VERSION_OK TRUE)
537
538  # check with DEFINED here as the requested or found version may be "0"
539  if (DEFINED ${_NAME}_FIND_VERSION)
540    if(DEFINED ${FPHSA_VERSION_VAR})
541      set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}})
542      if (FPHSA_HANDLE_VERSION_RANGE)
543        set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE)
544      else()
545        set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE)
546      endif()
547      find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG
548        ${FPCV_HANDLE_VERSION_RANGE})
549    else()
550      # if the package was not found, but a version was given, add that to the output:
551      if(${_NAME}_FIND_VERSION_EXACT)
552        set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")")
553      elseif (FPHSA_HANDLE_VERSION_RANGE AND ${_NAME}_FIND_VERSION_RANGE)
554        set(VERSION_MSG "(Required is version range \"${${_NAME}_FIND_VERSION_RANGE}\")")
555      else()
556        set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")")
557      endif()
558    endif()
559  else ()
560    # Check with DEFINED as the found version may be 0.
561    if(DEFINED ${FPHSA_VERSION_VAR})
562      set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")")
563    endif()
564  endif ()
565
566  if(VERSION_OK)
567    string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]")
568  else()
569    set(${_NAME}_FOUND FALSE)
570  endif()
571
572
573  # print the result:
574  if (${_NAME}_FOUND)
575    FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
576  else ()
577
578    if(FPHSA_CONFIG_MODE)
579      _FPHSA_HANDLE_FAILURE_CONFIG_MODE()
580    else()
581      if(NOT VERSION_OK)
582        set(RESULT_MSG)
583        if (_FIRST_REQUIRED_VAR)
584          string (APPEND RESULT_MSG "found ${${_FIRST_REQUIRED_VAR}}")
585        endif()
586        if (COMPONENT_MSG)
587          if (RESULT_MSG)
588            string (APPEND RESULT_MSG ", ")
589          endif()
590          string (APPEND RESULT_MSG "${FOUND_COMPONENTS_MSG}")
591        endif()
592        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (${RESULT_MSG})")
593      else()
594        _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}")
595      endif()
596    endif()
597
598  endif ()
599
600  set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
601  set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE)
602endfunction()
603
604
605cmake_policy(POP)
606