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