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: 5FeatureSummary 6-------------- 7 8Functions for generating a summary of enabled/disabled features. 9 10These functions can be used to generate a summary of enabled and disabled 11packages and/or feature for a build tree such as:: 12 13 -- The following OPTIONAL packages have been found: 14 LibXml2 (required version >= 2.4), XML processing lib, <http://xmlsoft.org> 15 * Enables HTML-import in MyWordProcessor 16 * Enables odt-export in MyWordProcessor 17 PNG, A PNG image library., <http://www.libpng.org/pub/png/> 18 * Enables saving screenshots 19 -- The following OPTIONAL packages have not been found: 20 Lua51, The Lua scripting language., <http://www.lua.org> 21 * Enables macros in MyWordProcessor 22 Foo, Foo provides cool stuff. 23 24Global Properties 25^^^^^^^^^^^^^^^^^ 26 27.. variable:: FeatureSummary_PKG_TYPES 28 29The global property :variable:`FeatureSummary_PKG_TYPES` defines the type of 30packages used by `FeatureSummary`. 31 32The order in this list is important, the first package type in the list is the 33least important, the last is the most important. the of a package can only be 34changed to higher types. 35 36The default package types are , ``RUNTIME``, ``OPTIONAL``, ``RECOMMENDED`` and 37``REQUIRED``, and their importance is 38``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``. 39 40 41.. variable:: FeatureSummary_REQUIRED_PKG_TYPES 42 43The global property :variable:`FeatureSummary_REQUIRED_PKG_TYPES` defines which 44package types are required. 45 46If one or more package in this categories has not been found, CMake will abort 47when calling :command:`feature_summary` with the 48'FATAL_ON_MISSING_REQUIRED_PACKAGES' option enabled. 49 50The default value for this global property is ``REQUIRED``. 51 52 53.. variable:: FeatureSummary_DEFAULT_PKG_TYPE 54 55The global property :variable:`FeatureSummary_DEFAULT_PKG_TYPE` defines which 56package type is the default one. 57When calling :command:`feature_summary`, if the user did not set the package type 58explicitly, the package will be assigned to this category. 59 60This value must be one of the types defined in the 61:variable:`FeatureSummary_PKG_TYPES` global property unless the package type 62is set for all the packages. 63 64The default value for this global property is ``OPTIONAL``. 65 66 67.. variable:: FeatureSummary_<TYPE>_DESCRIPTION 68 69.. versionadded:: 3.9 70 71The global property :variable:`FeatureSummary_<TYPE>_DESCRIPTION` can be defined 72for each type to replace the type name with the specified string whenever the 73package type is used in an output string. 74 75If not set, the string "``<TYPE>`` packages" is used. 76 77 78#]=======================================================================] 79 80get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET) 81if(NOT _fsPkgTypeIsSet) 82 set_property(GLOBAL PROPERTY FeatureSummary_PKG_TYPES RUNTIME OPTIONAL RECOMMENDED REQUIRED) 83endif() 84 85get_property(_fsReqPkgTypesIsSet GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES SET) 86if(NOT _fsReqPkgTypesIsSet) 87 set_property(GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES REQUIRED) 88endif() 89 90get_property(_fsDefaultPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE SET) 91if(NOT _fsDefaultPkgTypeIsSet) 92 set_property(GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE OPTIONAL) 93endif() 94 95#[=======================================================================[.rst: 96 97Functions 98^^^^^^^^^ 99 100#]=======================================================================] 101 102function(_FS_GET_FEATURE_SUMMARY _property _var _includeQuiet) 103 104 get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES) 105 get_property(_fsDefaultPkgType GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE) 106 107 set(_type "ANY") 108 foreach(_fsPkgType ${_fsPkgTypes}) 109 if("${_property}" MATCHES "${_fsPkgType}_PACKAGES_(NOT_)?FOUND") 110 set(_type "${_fsPkgType}") 111 break() 112 endif() 113 endforeach() 114 115 if("${_property}" MATCHES "PACKAGES_FOUND") 116 set(_property "PACKAGES_FOUND") 117 elseif("${_property}" MATCHES "PACKAGES_NOT_FOUND") 118 set(_property "PACKAGES_NOT_FOUND") 119 endif() 120 121 122 set(_currentFeatureText "") 123 get_property(_EnabledFeatures GLOBAL PROPERTY ${_property}) 124 if(_EnabledFeatures) 125 list(REMOVE_DUPLICATES _EnabledFeatures) 126 endif(_EnabledFeatures) 127 128 foreach(_currentFeature ${_EnabledFeatures}) 129 130 # does this package belong to the type we currently want to list ? 131 get_property(_currentType GLOBAL PROPERTY _CMAKE_${_currentFeature}_TYPE) 132 if(NOT _currentType) 133 list(FIND _fsPkgTypes "${_fsDefaultPkgType}" _defaultInPkgTypes) 134 if("${_defaultInPkgTypes}" STREQUAL "-1") 135 string(REGEX REPLACE ";([^;]+)$" " and \\1" _fsPkgTypes_msg "${_fsPkgTypes}") 136 string(REPLACE ";" ", " _fsPkgTypes_msg "${_fsPkgTypes_msg}") 137 message(FATAL_ERROR "Bad package property type ${_fsDefaultPkgType} used in global property FeatureSummary_DEFAULT_PKG_TYPE. " 138 "Valid types are ${_fsPkgTypes_msg}. " 139 "Either update FeatureSummary_DEFAULT_PKG_TYPE or add ${_fsDefaultPkgType} to the FeatureSummary_PKG_TYPES global property.") 140 endif() 141 set(_currentType ${_fsDefaultPkgType}) 142 endif() 143 144 if("${_type}" STREQUAL ANY OR "${_type}" STREQUAL "${_currentType}") 145 # check whether the current feature/package should be in the output depending on whether it was QUIET or not 146 set(includeThisOne TRUE) 147 set(_required FALSE) 148 # skip QUIET packages, except if they are REQUIRED or INCLUDE_QUIET_PACKAGES has been set 149 get_property(_fsReqPkgTypes GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES) 150 foreach(_fsReqPkgType ${_fsReqPkgTypes}) 151 if("${_currentType}" STREQUAL "${_fsReqPkgType}") 152 set(_required TRUE) 153 break() 154 endif() 155 endforeach() 156 if(NOT _required AND NOT _includeQuiet) 157 get_property(_isQuiet GLOBAL PROPERTY _CMAKE_${_currentFeature}_QUIET) 158 if(_isQuiet) 159 set(includeThisOne FALSE) 160 endif() 161 endif() 162 get_property(_isTransitiveDepend 163 GLOBAL PROPERTY _CMAKE_${_currentFeature}_TRANSITIVE_DEPENDENCY 164 ) 165 if(_isTransitiveDepend) 166 set(includeThisOne FALSE) 167 endif() 168 169 if(includeThisOne) 170 171 string(APPEND _currentFeatureText "\n * ${_currentFeature}") 172 get_property(_info GLOBAL PROPERTY _CMAKE_${_currentFeature}_REQUIRED_VERSION) 173 if(_info) 174 string(APPEND _currentFeatureText " (required version ${_info})") 175 endif() 176 get_property(_info GLOBAL PROPERTY _CMAKE_${_currentFeature}_DESCRIPTION) 177 if(_info) 178 string(APPEND _currentFeatureText ", ${_info}") 179 endif() 180 get_property(_info GLOBAL PROPERTY _CMAKE_${_currentFeature}_URL) 181 if(_info) 182 string(APPEND _currentFeatureText ", <${_info}>") 183 endif() 184 185 get_property(_info GLOBAL PROPERTY _CMAKE_${_currentFeature}_PURPOSE) 186 foreach(_purpose ${_info}) 187 string(APPEND _currentFeatureText "\n ${_purpose}") 188 endforeach() 189 190 endif() 191 192 endif() 193 194 endforeach() 195 set(${_var} "${_currentFeatureText}" PARENT_SCOPE) 196endfunction() 197 198 199#[=======================================================================[.rst: 200.. command:: feature_summary 201 202 :: 203 204 feature_summary( [FILENAME <file>] 205 [APPEND] 206 [VAR <variable_name>] 207 [INCLUDE_QUIET_PACKAGES] 208 [FATAL_ON_MISSING_REQUIRED_PACKAGES] 209 [DESCRIPTION "<description>" | DEFAULT_DESCRIPTION] 210 [QUIET_ON_EMPTY] 211 WHAT (ALL 212 | PACKAGES_FOUND | PACKAGES_NOT_FOUND 213 | <TYPE>_PACKAGES_FOUND | <TYPE>_PACKAGES_NOT_FOUND 214 | ENABLED_FEATURES | DISABLED_FEATURES) 215 ) 216 217 The ``feature_summary()`` macro can be used to print information about 218 enabled or disabled packages or features of a project. By default, 219 only the names of the features/packages will be printed and their 220 required version when one was specified. Use ``set_package_properties()`` 221 to add more useful information, like e.g. a download URL for the 222 respective package or their purpose in the project. 223 224 The ``WHAT`` option is the only mandatory option. Here you specify what 225 information will be printed: 226 227 ``ALL`` 228 print everything 229 ``ENABLED_FEATURES`` 230 the list of all features which are enabled 231 ``DISABLED_FEATURES`` 232 the list of all features which are disabled 233 ``PACKAGES_FOUND`` 234 the list of all packages which have been found 235 ``PACKAGES_NOT_FOUND`` 236 the list of all packages which have not been found 237 238 For each package type ``<TYPE>`` defined by the 239 :variable:`FeatureSummary_PKG_TYPES` global property, the following 240 information can also be used: 241 242 ``<TYPE>_PACKAGES_FOUND`` 243 only those packages which have been found which have the type <TYPE> 244 ``<TYPE>_PACKAGES_NOT_FOUND`` 245 only those packages which have not been found which have the type <TYPE> 246 247 .. versionchanged:: 3.1 248 With the exception of the ``ALL`` value, these values can be combined 249 in order to customize the output. For example: 250 251 .. code-block:: cmake 252 253 feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES) 254 255 If a ``FILENAME`` is given, the information is printed into this file. If 256 ``APPEND`` is used, it is appended to this file, otherwise the file is 257 overwritten if it already existed. If the VAR option is used, the 258 information is "printed" into the specified variable. If ``FILENAME`` is 259 not used, the information is printed to the terminal. Using the 260 ``DESCRIPTION`` option a description or headline can be set which will be 261 printed above the actual content. If only one type of 262 package was requested, no title is printed, unless it is explicitly set using 263 either ``DESCRIPTION`` to use a custom string, or ``DEFAULT_DESCRIPTION`` to 264 use a default title for the requested type. 265 If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with 266 ``find_package(... QUIET)`` will also be listed. By default they are skipped. 267 If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a 268 package which is marked as one of the package types listed in the 269 :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global property has not been 270 found. 271 The default value for the :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global 272 property is ``REQUIRED``. 273 274 .. versionadded:: 3.9 275 The ``DEFAULT_DESCRIPTION`` option. 276 277 The :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global property can be 278 modified to change the default package type assigned when not explicitly 279 assigned by the user. 280 281 .. versionadded:: 3.8 282 If the ``QUIET_ON_EMPTY`` option is used, if only one type of package was 283 requested, and no packages belonging to that category were found, then no 284 output (including the ``DESCRIPTION``) is printed or added to the ``VAR`` 285 variable. 286 287 Example 1, append everything to a file: 288 289 .. code-block:: cmake 290 291 include(FeatureSummary) 292 feature_summary(WHAT ALL 293 FILENAME ${CMAKE_BINARY_DIR}/all.log APPEND) 294 295 Example 2, print the enabled features into the variable 296 enabledFeaturesText, including QUIET packages: 297 298 .. code-block:: cmake 299 300 include(FeatureSummary) 301 feature_summary(WHAT ENABLED_FEATURES 302 INCLUDE_QUIET_PACKAGES 303 DESCRIPTION "Enabled Features:" 304 VAR enabledFeaturesText) 305 message(STATUS "${enabledFeaturesText}") 306 307 Example 3, change default package types and print only the categories that 308 are not empty: 309 310 .. code-block:: cmake 311 312 include(FeatureSummary) 313 set_property(GLOBAL APPEND PROPERTY FeatureSummary_PKG_TYPES BUILD) 314 find_package(FOO) 315 set_package_properties(FOO PROPERTIES TYPE BUILD) 316 feature_summary(WHAT BUILD_PACKAGES_FOUND 317 Description "Build tools found:" 318 QUIET_ON_EMPTY) 319 feature_summary(WHAT BUILD_PACKAGES_NOT_FOUND 320 Description "Build tools not found:" 321 QUIET_ON_EMPTY) 322 323#]=======================================================================] 324 325function(FEATURE_SUMMARY) 326# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...) 327 set(options APPEND 328 INCLUDE_QUIET_PACKAGES 329 FATAL_ON_MISSING_REQUIRED_PACKAGES 330 QUIET_ON_EMPTY 331 DEFAULT_DESCRIPTION) 332 set(oneValueArgs FILENAME 333 VAR 334 DESCRIPTION) 335 set(multiValueArgs WHAT) 336 337 CMAKE_PARSE_ARGUMENTS(_FS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) 338 339 if(_FS_UNPARSED_ARGUMENTS) 340 message(FATAL_ERROR "Unknown keywords given to FEATURE_SUMMARY(): \"${_FS_UNPARSED_ARGUMENTS}\"") 341 endif() 342 343 if(NOT _FS_WHAT) 344 message(FATAL_ERROR "The call to FEATURE_SUMMARY() doesn't set the required WHAT argument.") 345 endif() 346 347 if(_FS_DEFAULT_DESCRIPTION AND DEFINED _FS_DESCRIPTION) 348 message(WARNING "DEFAULT_DESCRIPTION option discarded since DESCRIPTION is set.") 349 set(_FS_DEFAULT_DESCRIPTION 0) 350 endif() 351 352 set(validWhatParts "ENABLED_FEATURES" 353 "DISABLED_FEATURES" 354 "PACKAGES_FOUND" 355 "PACKAGES_NOT_FOUND") 356 357 get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES) 358 get_property(_fsReqPkgTypes GLOBAL PROPERTY FeatureSummary_REQUIRED_PKG_TYPES) 359 foreach(_fsPkgType ${_fsPkgTypes}) 360 list(APPEND validWhatParts "${_fsPkgType}_PACKAGES_FOUND" 361 "${_fsPkgType}_PACKAGES_NOT_FOUND") 362 endforeach() 363 364 set(title_ENABLED_FEATURES "The following features have been enabled:") 365 set(title_DISABLED_FEATURES "The following features have been disabled:") 366 set(title_PACKAGES_FOUND "The following packages have been found:") 367 set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") 368 foreach(_fsPkgType ${_fsPkgTypes}) 369 set(_fsPkgTypeDescription "${_fsPkgType} packages") 370 get_property(_fsPkgTypeDescriptionIsSet GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION SET) 371 if(_fsPkgTypeDescriptionIsSet) 372 get_property(_fsPkgTypeDescription GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION ) 373 endif() 374 set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgTypeDescription} have been found:") 375 set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgTypeDescription} have not been found:") 376 endforeach() 377 378 list(FIND validWhatParts "${_FS_WHAT}" indexInList) 379 if(NOT "${indexInList}" STREQUAL "-1") 380 _FS_GET_FEATURE_SUMMARY( ${_FS_WHAT} _featureSummary ${_FS_INCLUDE_QUIET_PACKAGES} ) 381 if(_featureSummary OR NOT _FS_QUIET_ON_EMPTY) 382 if(_FS_DEFAULT_DESCRIPTION) 383 set(_fullText "${title_${_FS_WHAT}}\n${_featureSummary}\n") 384 else() 385 set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n") 386 endif() 387 endif() 388 389 if(_featureSummary) 390 foreach(_fsReqPkgType ${_fsReqPkgTypes}) 391 if("${_FS_WHAT}" STREQUAL "${_fsReqPkgType}_PACKAGES_NOT_FOUND") 392 set(requiredPackagesNotFound TRUE) 393 break() 394 endif() 395 endforeach() 396 endif() 397 398 else() 399 if("${_FS_WHAT}" STREQUAL "ALL") 400 401 set(allWhatParts "ENABLED_FEATURES") 402 foreach(_fsPkgType ${_fsPkgTypes}) 403 list(APPEND allWhatParts "${_fsPkgType}_PACKAGES_FOUND") 404 endforeach() 405 list(APPEND allWhatParts "DISABLED_FEATURES") 406 foreach(_fsPkgType ${_fsPkgTypes}) 407 list(APPEND allWhatParts "${_fsPkgType}_PACKAGES_NOT_FOUND") 408 endforeach() 409 else() 410 set(allWhatParts) 411 foreach(part ${_FS_WHAT}) 412 list(FIND validWhatParts "${part}" indexInList) 413 if(NOT "${indexInList}" STREQUAL "-1") 414 list(APPEND allWhatParts "${part}") 415 else() 416 if("${part}" STREQUAL "ALL") 417 message(FATAL_ERROR "The WHAT argument of FEATURE_SUMMARY() contains ALL, which cannot be combined with other values.") 418 else() 419 message(FATAL_ERROR "The WHAT argument of FEATURE_SUMMARY() contains ${part}, which is not a valid value.") 420 endif() 421 endif() 422 endforeach() 423 endif() 424 425 set(_fullText "${_FS_DESCRIPTION}") 426 foreach(part ${allWhatParts}) 427 set(_tmp) 428 _FS_GET_FEATURE_SUMMARY( ${part} _tmp ${_FS_INCLUDE_QUIET_PACKAGES}) 429 if(_tmp) 430 if(_fullText) 431 string(APPEND _fullText "\n-- ") 432 endif() 433 string(APPEND _fullText "${title_${part}}\n${_tmp}\n") 434 foreach(_fsReqPkgType ${_fsReqPkgTypes}) 435 if("${part}" STREQUAL "${_fsReqPkgType}_PACKAGES_NOT_FOUND") 436 set(requiredPackagesNotFound TRUE) 437 break() 438 endif() 439 endforeach() 440 endif() 441 endforeach() 442 endif() 443 444 if(_fullText OR NOT _FS_QUIET_ON_EMPTY) 445 if(_FS_FILENAME) 446 if(_FS_APPEND) 447 file(APPEND "${_FS_FILENAME}" "${_fullText}") 448 else() 449 file(WRITE "${_FS_FILENAME}" "${_fullText}") 450 endif() 451 452 else() 453 if(NOT _FS_VAR) 454 message(STATUS "${_fullText}") 455 endif() 456 endif() 457 458 if(_FS_VAR) 459 set(${_FS_VAR} "${_fullText}" PARENT_SCOPE) 460 endif() 461 endif() 462 463 if(requiredPackagesNotFound AND _FS_FATAL_ON_MISSING_REQUIRED_PACKAGES) 464 message(FATAL_ERROR "feature_summary() Error: REQUIRED package(s) are missing, aborting CMake run.") 465 endif() 466 467endfunction() 468 469#[=======================================================================[.rst: 470.. command:: set_package_properties 471 472 :: 473 474 set_package_properties(<name> PROPERTIES 475 [ URL <url> ] 476 [ DESCRIPTION <description> ] 477 [ TYPE (RUNTIME|OPTIONAL|RECOMMENDED|REQUIRED) ] 478 [ PURPOSE <purpose> ] 479 ) 480 481 Use this macro to set up information about the named package, which 482 can then be displayed via FEATURE_SUMMARY(). This can be done either 483 directly in the Find-module or in the project which uses the module 484 after the find_package() call. The features for which information can 485 be set are added automatically by the find_package() command. 486 487 ``URL <url>`` 488 This should be the homepage of the package, or something similar. 489 Ideally this is set already directly in the Find-module. 490 491 ``DESCRIPTION <description>`` 492 A short description what that package is, at most one sentence. 493 Ideally this is set already directly in the Find-module. 494 495 ``TYPE <type>`` 496 What type of dependency has the using project on that package. 497 Default is ``OPTIONAL``. In this case it is a package which can be used 498 by the project when available at buildtime, but it also work without. 499 ``RECOMMENDED`` is similar to ``OPTIONAL``, i.e. the project will build if 500 the package is not present, but the functionality of the resulting 501 binaries will be severely limited. If a ``REQUIRED`` package is not 502 available at buildtime, the project may not even build. This can be 503 combined with the ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` argument for 504 ``feature_summary()``. Last, a ``RUNTIME`` package is a package which is 505 actually not used at all during the build, but which is required for 506 actually running the resulting binaries. So if such a package is 507 missing, the project can still be built, but it may not work later on. 508 If ``set_package_properties()`` is called multiple times for the same 509 package with different TYPEs, the ``TYPE`` is only changed to higher 510 TYPEs (``RUNTIME < OPTIONAL < RECOMMENDED < REQUIRED``), lower TYPEs are 511 ignored. The ``TYPE`` property is project-specific, so it cannot be set 512 by the Find-module, but must be set in the project. 513 Type accepted can be changed by setting the 514 :variable:`FeatureSummary_PKG_TYPES` global property. 515 516 ``PURPOSE <purpose>`` 517 This describes which features this package enables in the 518 project, i.e. it tells the user what functionality he gets in the 519 resulting binaries. If set_package_properties() is called multiple 520 times for a package, all PURPOSE properties are appended to a list of 521 purposes of the package in the project. As the TYPE property, also 522 the PURPOSE property is project-specific, so it cannot be set by the 523 Find-module, but must be set in the project. 524 525 Example for setting the info for a package: 526 527 .. code-block:: cmake 528 529 find_package(LibXml2) 530 set_package_properties(LibXml2 PROPERTIES 531 DESCRIPTION "A XML processing library." 532 URL "http://xmlsoft.org/") 533 # or 534 set_package_properties(LibXml2 PROPERTIES 535 TYPE RECOMMENDED 536 PURPOSE "Enables HTML-import in MyWordProcessor") 537 # or 538 set_package_properties(LibXml2 PROPERTIES 539 TYPE OPTIONAL 540 PURPOSE "Enables odt-export in MyWordProcessor") 541 542 find_package(DBUS) 543 set_package_properties(DBUS PROPERTIES 544 TYPE RUNTIME 545 PURPOSE "Necessary to disable the screensaver during a presentation") 546#]=======================================================================] 547function(SET_PACKAGE_PROPERTIES _name _props) 548 if(NOT "${_props}" STREQUAL "PROPERTIES") 549 message(FATAL_ERROR "PROPERTIES keyword is missing in SET_PACKAGE_PROPERTIES() call.") 550 endif() 551 552 set(options ) # none 553 set(oneValueArgs DESCRIPTION URL TYPE PURPOSE ) 554 set(multiValueArgs ) # none 555 556 CMAKE_PARSE_ARGUMENTS(_SPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 557 558 if(_SPP_UNPARSED_ARGUMENTS) 559 message(FATAL_ERROR "Unknown keywords given to SET_PACKAGE_PROPERTIES(): \"${_SPP_UNPARSED_ARGUMENTS}\"") 560 endif() 561 562 if(_SPP_DESCRIPTION) 563 get_property(_info GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION) 564 if(_info AND NOT "${_info}" STREQUAL "${_SPP_DESCRIPTION}") 565 message(STATUS "Warning: Property DESCRIPTION for package ${_name} already set to \"${_info}\", overriding it with \"${_SPP_DESCRIPTION}\"") 566 endif() 567 568 set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_SPP_DESCRIPTION}" ) 569 endif() 570 571 572 if(_SPP_URL) 573 get_property(_info GLOBAL PROPERTY _CMAKE_${_name}_URL) 574 if(_info AND NOT "${_info}" STREQUAL "${_SPP_URL}") 575 message(STATUS "Warning: Property URL already set to \"${_info}\", overriding it with \"${_SPP_URL}\"") 576 endif() 577 578 set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_SPP_URL}" ) 579 endif() 580 581 582 # handle the PURPOSE: use APPEND, since there can be multiple purposes for one package inside a project 583 if(_SPP_PURPOSE) 584 set_property(GLOBAL APPEND PROPERTY _CMAKE_${_name}_PURPOSE "${_SPP_PURPOSE}" ) 585 endif() 586 587 get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES) 588 get_property(_fsDefaultPkgType GLOBAL PROPERTY FeatureSummary_DEFAULT_PKG_TYPE) 589 590 # handle the TYPE 591 if(DEFINED _SPP_TYPE) 592 # Supported types are listed in FeatureSummary_PKG_TYPES according to their priority 593 get_property(_fsPkgTypes GLOBAL PROPERTY FeatureSummary_PKG_TYPES) 594 list(FIND _fsPkgTypes ${_SPP_TYPE} _typeIndexInList) 595 if("${_typeIndexInList}" STREQUAL "-1" ) 596 string(REGEX REPLACE ";([^;]+)$" " and \\1" _fsPkgTypes_msg "${_fsPkgTypes}") 597 string(REPLACE ";" ", " _fsPkgTypes_msg "${_fsPkgTypes_msg}") 598 message(FATAL_ERROR "Bad package property type ${_SPP_TYPE} used in SET_PACKAGE_PROPERTIES(). " 599 "Valid types are ${_fsPkgTypes_msg}." ) 600 endif() 601 602 get_property(_previousType GLOBAL PROPERTY _CMAKE_${_name}_TYPE) 603 list(FIND _fsPkgTypes "${_previousType}" _prevTypeIndexInList) 604 605 # make sure a previously set TYPE is not overridden with a lower new TYPE: 606 if("${_typeIndexInList}" GREATER "${_prevTypeIndexInList}") 607 set_property(GLOBAL PROPERTY _CMAKE_${_name}_TYPE "${_SPP_TYPE}" ) 608 endif() 609 endif() 610 611endfunction() 612 613#[=======================================================================[.rst: 614.. command:: add_feature_info 615 616 :: 617 618 add_feature_info(<name> <enabled> <description>) 619 620 Use this macro to add information about a feature with the given ``<name>``. 621 ``<enabled>`` contains whether this feature is enabled or not. It can be a 622 variable or a list of conditions. 623 ``<description>`` is a text describing the feature. The information can 624 be displayed using ``feature_summary()`` for ``ENABLED_FEATURES`` and 625 ``DISABLED_FEATURES`` respectively. 626 627 .. versionchanged:: 3.8 628 ``<enabled>`` can be a list of conditions. 629 630 Example for setting the info for a feature: 631 632 .. code-block:: cmake 633 634 option(WITH_FOO "Help for foo" ON) 635 add_feature_info(Foo WITH_FOO "The Foo feature provides very cool stuff.") 636#]=======================================================================] 637function(ADD_FEATURE_INFO _name _depends _desc) 638 set(_enabled 1) 639 foreach(_d ${_depends}) 640 string(REGEX REPLACE " +" ";" _d "${_d}") 641 if(${_d}) 642 else() 643 set(_enabled 0) 644 break() 645 endif() 646 endforeach() 647 if (${_enabled}) 648 set_property(GLOBAL APPEND PROPERTY ENABLED_FEATURES "${_name}") 649 else () 650 set_property(GLOBAL APPEND PROPERTY DISABLED_FEATURES "${_name}") 651 endif () 652 653 set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_desc}" ) 654endfunction() 655 656 657# The stuff below is only kept for compatibility 658 659#[=======================================================================[.rst: 660Legacy Macros 661^^^^^^^^^^^^^ 662 663The following macros are provided for compatibility with previous 664CMake versions: 665 666.. command:: set_package_info 667 668 :: 669 670 set_package_info(<name> <description> [ <url> [<purpose>] ]) 671 672 Use this macro to set up information about the named package, which 673 can then be displayed via ``feature_summary()``. This can be done either 674 directly in the Find-module or in the project which uses the module 675 after the :command:`find_package` call. The features for which information 676 can be set are added automatically by the ``find_package()`` command. 677#]=======================================================================] 678function(SET_PACKAGE_INFO _name _desc) 679 message(DEPRECATION "SET_PACKAGE_INFO is deprecated. Use SET_PACKAGE_PROPERTIES instead.") 680 unset(_url) 681 unset(_purpose) 682 if(ARGC GREATER 2) 683 set(_url "${ARGV2}") 684 endif() 685 if(ARGC GREATER 3) 686 set(_purpose "${ARGV3}") 687 endif() 688 set_property(GLOBAL PROPERTY _CMAKE_${_name}_DESCRIPTION "${_desc}" ) 689 if(NOT _url STREQUAL "") 690 set_property(GLOBAL PROPERTY _CMAKE_${_name}_URL "${_url}" ) 691 endif() 692 if(NOT _purpose STREQUAL "") 693 set_property(GLOBAL APPEND PROPERTY _CMAKE_${_name}_PURPOSE "${_purpose}" ) 694 endif() 695endfunction() 696 697#[=======================================================================[.rst: 698.. command:: set_feature_info 699 700 :: 701 702 set_feature_info(<name> <description> [<url>]) 703 704 Does the same as:: 705 706 set_package_info(<name> <description> <url>) 707#]=======================================================================] 708function(SET_FEATURE_INFO) 709 message(DEPRECATION "SET_FEATURE_INFO is deprecated. Use ADD_FEATURE_INFO instead.") 710 SET_PACKAGE_INFO(${ARGN}) 711endfunction() 712 713#[=======================================================================[.rst: 714.. command:: print_enabled_features 715 716 :: 717 718 print_enabled_features() 719 720 Does the same as 721 722 .. code-block:: cmake 723 724 feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") 725#]=======================================================================] 726function(PRINT_ENABLED_FEATURES) 727 message(DEPRECATION "PRINT_ENABLED_FEATURES is deprecated. Use 728 feature_summary(WHAT ENABLED_FEATURES DESCRIPTION \"Enabled features:\")") 729 FEATURE_SUMMARY(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") 730endfunction() 731 732#[=======================================================================[.rst: 733.. command:: print_disabled_features 734 735 :: 736 737 print_disabled_features() 738 739 Does the same as 740 741 .. code-block:: cmake 742 743 feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") 744#]=======================================================================] 745function(PRINT_DISABLED_FEATURES) 746 message(DEPRECATION "PRINT_DISABLED_FEATURES is deprecated. Use 747 feature_summary(WHAT DISABLED_FEATURES DESCRIPTION \"Disabled features:\")") 748 FEATURE_SUMMARY(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") 749endfunction() 750