#[==[ @defgroup module Module CMake APIs @defgroup module-internal Module Internal CMake APIs @defgroup module-impl Module Implementation CMake APIs @defgroup module-support Module Support CMake APIs #]==] #[==[ @ingroup module @page module-api-overview Module API This module includes functions to find and build VTK modules. A module is a set of related functionality. These are then compiled together into libraries at the "kit" level. Each module may be enabled or disabled individually and its dependencies will be built as needed. All functions strictly check their arguments. Any unrecognized or invalid values for a function cause errors to be raised. #]==] #[==[ @ingroup module-internal @page module-internal-api Internal API The VTK module system provides some API functions for use by other code which consumes VTK modules (primarily language wrappers). This file documents these APIs. They may start with `_vtk_module`, but they are intended for use in cases of language wrappers or dealing with trickier third party packages. #]==] #[==[ @ingroup module-impl @page module-impl-api Implementation API These functions are purely internal implementation details. No guarantees are made for them and they may change at any time (including wrapping code calls). Note that these functions are usually very lax in their argument parsing. #]==] #[==[ @ingroup module-internal @brief Conditionally output debug statements The @ref _vtk_module_debug function is provided to assist in debugging. It is controlled by the `_vtk_module_log` variable which contains a list of "domains" to debug. ~~~ _vtk_module_debug( ) ~~~ If the `domain` is enabled for debugging, the `format` argument is configured and printed. It should contain `@` variable expansions to replace rather than it being done outside. This helps to avoid the cost of generating large strings when debugging is disabled. #]==] function (_vtk_module_debug domain format) if (NOT _vtk_module_log STREQUAL "ALL" AND NOT domain IN_LIST _vtk_module_log) return () endif () string(CONFIGURE "${format}" _vtk_module_debug_msg) if (_vtk_module_debug_msg) message(STATUS "VTK module debug ${domain}: ${_vtk_module_debug_msg}") endif () endfunction () # TODO: Support finding `vtk.module` and `vtk.kit` contents in the # `CMakeLists.txt` files for the module via a comment header. #[==[ @ingroup module @brief Find `vtk.kit` files in a set of directories ~~~ vtk_module_find_kits( [...]) ~~~ This scans the given directories recursively for `vtk.kit` files and put the paths into the output variable. #]==] function (vtk_module_find_kits output) set(_vtk_find_kits_all) foreach (_vtk_find_kits_directory IN LISTS ARGN) file(GLOB_RECURSE _vtk_find_kits_kits "${_vtk_find_kits_directory}/vtk.kit") list(APPEND _vtk_find_kits_all ${_vtk_find_kits_kits}) endforeach () set("${output}" ${_vtk_find_kits_all} PARENT_SCOPE) endfunction () #[==[ @ingroup module @brief Find `vtk.module` files in a set of directories ~~~ vtk_module_find_modules( [...]) ~~~ This scans the given directories recursively for `vtk.module` files and put the paths into the output variable. Note that module files are assumed to live next to the `CMakeLists.txt` file which will build the module. #]==] function (vtk_module_find_modules output) set(_vtk_find_modules_all) foreach (_vtk_find_modules_directory IN LISTS ARGN) file(GLOB_RECURSE _vtk_find_modules_modules "${_vtk_find_modules_directory}/vtk.module") list(APPEND _vtk_find_modules_all ${_vtk_find_modules_modules}) endforeach () set("${output}" ${_vtk_find_modules_all} PARENT_SCOPE) endfunction () #[==[ @ingroup module-internal @brief Split a module name into a namespace and target component Module names may include a namespace. This function splits the name into a namespace and target name part. ~~~ _vtk_module_split_module_name( ) ~~~ The `_NAMESPACE` and `_TARGET_NAME` variables will be set in the calling scope. #]==] function (_vtk_module_split_module_name name prefix) string(FIND "${name}" "::" namespace_pos) if (namespace_pos EQUAL -1) set(namespace "") set(target_name "${name}") else () string(SUBSTRING "${name}" 0 "${namespace_pos}" namespace) math(EXPR name_pos "${namespace_pos} + 2") string(SUBSTRING "${name}" "${name_pos}" -1 target_name) endif () set("${prefix}_NAMESPACE" "${namespace}" PARENT_SCOPE) set("${prefix}_TARGET_NAME" "${target_name}" PARENT_SCOPE) endfunction () #[==[ @ingroup module @page module-overview Module overview @section module-parse-module vtk.module file contents The `vtk.module` file is parsed and used as arguments to a CMake function which stores information about the module for use when building it. Note that no variable expansion is allowed and it is not CMake code, so no control flow is allowed. Comments are supported and any content after a `#` on a line is treated as a comment. Due to the breakdown of the content, quotes are not meaningful within the files. Example: ~~~ NAME VTK::CommonCore LIBRARY_NAME vtkCommonCore DESCRIPTION The base VTK library. LICENSE_FILES Copyright.txt GROUPS StandAlone DEPENDS VTK::kwiml PRIVATE_DEPENDS VTK::vtksys VTK::utf8 ~~~ All values are optional unless otherwise noted. The following arguments are supported: * `NAME`: (Required) The name of the module. * `LIBRARY_NAME`: The base name of the library file. It defaults to the module name, but any namespaces are removed. For example, a `NS::Foo` module will have a default `LIBRARY_NAME` of `Foo`. * `DESCRIPTION`: (Recommended) Short text describing what the module is for. * `KIT`: The name of the kit the module belongs to (see `Kits files` for more information). * `IMPLEMENTABLE`: If present, the module contains logic which supports the autoinit functionality. * `GROUPS`: Modules may belong to "groups" which is exposed as a build option. This allows for enabling a set of modules with a single build option. * `CONDITION`: Arguments to CMake's `if` command which may be used to hide the module for certain platforms or other reasons. If the expression is false, the module is completely ignored. * `DEPENDS`: A list of modules which are required by this module and modules using this module. * `PRIVATE_DEPENDS`: A list of modules which are required by this module, but not by those using this module. * `OPTIONAL_DEPENDS`: A list of modules which are used by this module if enabled; these are treated as `PRIVATE_DEPENDS` if they exist. * `ORDER_DEPENDS`: Dependencies which only matter for ordering. This does not mean that the module will be enabled, just guaranteed to build before this module. * `IMPLEMENTS`: A list of modules for which this module needs to register with. * `TEST_DEPENDS`: Modules required by the test suite for this module. * `TEST_OPTIONAL_DEPENDS`: Modules used by the test suite for this module if available. * `TEST_LABELS`: Labels to apply to the tests of this module. By default, the module name is applied as a label. * `EXCLUDE_WRAP`: If present, this module should not be wrapped in any language. * `THIRD_PARTY`: If present, this module is a third party module. * `LICENSE_FILES`: A list of license files to install for the module. Optional. #]==] #[==[ @ingroup module-impl @brief Parse `vtk.module` file contents This macro places all `vtk.module` keyword "arguments" into the caller's scope prefixed with the value of `name_output` which is set to the `NAME` of the module. ~~~ _vtk_module_parse_module_args(name_output ) ~~~ For example, this `vtk.module` file: ~~~ NAME Namespace::Target LIBRARY_NAME nsTarget ~~~ called with `_vtk_module_parse_module_args(name ...)` will set the following variables in the calling scope: - `name`: `Namespace::Target` - `Namespace::Target_LIBRARY_NAME`: `nsTarget` With namespace support for module names, the variable should instead be referenced via `${${name}_LIBRARY_NAME}` instead. #]==] macro (_vtk_module_parse_module_args name_output) cmake_parse_arguments("_name" "" "NAME" "" ${ARGN}) if (NOT _name_NAME) message(FATAL_ERROR "A VTK module requires a name (from ${_vtk_scan_module_file}).") endif () set("${name_output}" "${_name_NAME}") cmake_parse_arguments("${_name_NAME}" "IMPLEMENTABLE;EXCLUDE_WRAP;THIRD_PARTY" "LIBRARY_NAME;NAME;KIT" "GROUPS;DEPENDS;PRIVATE_DEPENDS;OPTIONAL_DEPENDS;ORDER_DEPENDS;TEST_DEPENDS;TEST_OPTIONAL_DEPENDS;TEST_LABELS;DESCRIPTION;CONDITION;IMPLEMENTS;LICENSE_FILES" ${ARGN}) if (${_name_NAME}_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for ${_name_NAME}: " "${${_name_NAME}_UNPARSED_ARGUMENTS}") endif () if (NOT ${_name_NAME}_DESCRIPTION AND _vtk_module_warnings) message(WARNING "The ${_name_NAME} module should have a description") endif () string(REPLACE ";" " " "${_name_NAME}_DESCRIPTION" "${${_name_NAME}_DESCRIPTION}") _vtk_module_split_module_name("${_name_NAME}" "${_name_NAME}") if (NOT DEFINED "${_name_NAME}_LIBRARY_NAME") set("${_name_NAME}_LIBRARY_NAME" "${${_name_NAME}_TARGET_NAME}") endif () if (NOT ${_name_NAME}_LIBRARY_NAME) message(FATAL_ERROR "The ${_name_NAME} module must have a non-empty `LIBRARY_NAME`.") endif () list(APPEND "${_name_NAME}_TEST_LABELS" "${${_name_NAME}_NAME}" "${${_name_NAME}_LIBRARY_NAME}") endmacro () #[==[ @page module-overview @section module-parse-kit vtk.kit file contents The `vtk.kit` file is parsed similarly to `vtk.module` files. Kits are intended to bring together related modules into a single library in order to reduce the number of objects that linkers need to deal with. Example: ~~~ NAME VTK::Common LIBRARY_NAME vtkCommon DESCRIPTION Core utilities for VTK. ~~~ All values are optional unless otherwise noted. The following arguments are supported: * `NAME`: (Required) The name of the kit. * `LIBRARY_NAME`: The base name of the library file. It defaults to the module name, but any namespaces are removed. For example, a `NS::Foo` module will have a default `LIBRARY_NAME` of `Foo`. * `DESCRIPTION`: (Recommended) Short text describing what the kit contains. #]==] #[==[ @ingroup module-impl @brief Parse `vtk.kit` file contents Just like @ref _vtk_module_parse_module_args, but for kits. #]==] macro (_vtk_module_parse_kit_args name_output) cmake_parse_arguments("_name" "" "NAME" "" ${ARGN}) if (NOT _name_NAME) message(FATAL_ERROR "A VTK kit requires a name (from ${_vtk_scan_kit_file}).") endif () set("${name_output}" "${_name_NAME}") cmake_parse_arguments("${_name_NAME}" "" "NAME;LIBRARY_NAME" "DESCRIPTION" ${ARGN}) if (${_name_NAME}_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for ${_name_NAME}: " "${${_name_NAME}_UNPARSED_ARGUMENTS}") endif () _vtk_module_split_module_name("${_name_NAME}" "${_name_NAME}") if (NOT DEFINED "${_name_NAME}_LIBRARY_NAME") set("${_name_NAME}_LIBRARY_NAME" "${${_name_NAME}_TARGET_NAME}") endif () if (NOT ${_name_NAME}_LIBRARY_NAME) message(FATAL_ERROR "The ${_name_NAME} module must have a non-empty `LIBRARY_NAME`.") endif () if (NOT ${_name_NAME}_DESCRIPTION AND _vtk_module_warnings) message(WARNING "The ${_name_NAME} kit should have a description") endif () string(REPLACE ";" " " "${_name_NAME}_DESCRIPTION" "${${_name_NAME}_DESCRIPTION}") endmacro () #[==[ @page module-overview @ingroup module @section module-enable-status Enable status values Modules and groups are enable and disable preferences are specified using a 5-way flag setting: - `YES`: The module or group must be built. - `NO`: The module or group must not be built. - `WANT`: The module or group should be built if possible. - `DONT_WANT`: The module or group should only be built if required (e.g., via a dependency). - `DEFAULT`: Acts as either `WANT` or `DONT_WANT` based on the group settings for the module or `WANT_BY_DEFAULT` option to @ref vtk_module_scan if no other preference is specified. This is usually handled via another setting in the main project. If a `YES` module preference requires a module with a `NO` preference, an error is raised. A module with a setting of `DEFAULT` will look for its first non-`DEFAULT` group setting and only if all of those are set to `DEFAULT` is the `WANT_BY_DEFAULT` setting used. #]==] #[==[ @ingroup module-impl @brief Verify enable values Verifies that the variable named as the first parameter is a valid `enable status` value. ~~~ _vtk_module_verify_enable_value(var) ~~~ #]==] function (_vtk_module_verify_enable_value var) if (NOT (${var} STREQUAL "YES" OR ${var} STREQUAL "WANT" OR ${var} STREQUAL "DONT_WANT" OR ${var} STREQUAL "NO" OR ${var} STREQUAL "DEFAULT")) message(FATAL_ERROR "The `${var}` variable must be one of `YES`, `WANT`, `DONT_WANT`, `NO`, " "or `DEFAULT`. Found `${${var}}`.") endif () endfunction () include("${CMAKE_CURRENT_LIST_DIR}/vtkTopologicalSort.cmake") #[==[ @ingroup module @brief Scan modules and kits Once all of the modules and kits files have been found, they are "scanned" to determine what modules are enabled or required. ~~~ vtk_module_scan( MODULE_FILES ... [KIT_FILES ...] PROVIDES_MODULES [PROVIDES_KITS ] [REQUIRES_MODULES ] [REQUEST_MODULES ...] [REJECT_MODULES ...] [UNRECOGNIZED_MODULES ] [WANT_BY_DEFAULT ] [HIDE_MODULES_FROM_CACHE ] [ENABLE_TESTS ]) ~~~ The `MODULE_FILES` and `PROVIDES_MODULES` arguments are required. Modules which refer to kits must be scanned at the same time as their kits. This is so that modules may not add themselves to kits declared prior. The arguments are as follows: * `MODULE_FILES`: (Required) The list of module files to scan. * `KIT_FILES`: The list of kit files to scan. * `PROVIDES_MODULES`: (Required) This variable will contain the list of modules which are enabled due to this scan. * `PROVIDES_KITS`: (Required if `KIT_FILES` are provided) This variable will contain the list of kits which are enabled due to this scan. * `REQUIRES_MODULES`: This variable will contain the list of modules required by the enabled modules that were not scanned. * `REQUEST_MODULES`: The list of modules required by previous scans. * `REJECT_MODULES`: The list of modules to exclude from the scan. If any of these modules are required, an error will be raised. * `UNRECOGNIZED_MODULES`: This variable will contain the list of requested modules that were not scanned. * `WANT_BY_DEFAULT`: (Defaults to `OFF`) Whether modules should default to being built or not. * `HIDE_MODULES_FROM_CACHE`: (Defaults to `OFF`) Whether or not to hide the control variables from the cache or not. If enabled, modules will not be built unless they are required elsewhere. * `ENABLE_TESTS`: (Defaults to `DEFAULT`) Whether or not modules required by the tests for the scanned modules should be enabled or not. - `ON`: Modules listed as `TEST_DEPENDS` will be required. - `OFF`: Test modules will not be considered. - `WANT`: Test dependencies will enable modules if possible. Note that this has known issues where modules required only via testing may not have their dependencies enabled. - `DEFAULT`: Test modules will be enabled if their required dependencies are satisfied and skipped otherwise. To make error messages clearer, modules passed to `REQUIRES_MODULES` and `REJECT_MODULES` may have a `_vtk_module_reason_` variable set to the reason for the module appearing in either argument. For example, if the `Package::Frobnitz` module is required due to a `ENABLE_FROBNITZ` cache variable: ~~~{.cmake} set("_vtk_module_reason_Package::Frobnitz" "via the `ENABLE_FROBNITZ` setting") ~~~ Additionally, the reason for the `WANT_BY_DEFAULT` value may be provided via the `_vtk_module_reason_WANT_BY_DEFAULT` variable. @section module-scanning-multiple Scanning multiple groups of modules When scanning complicated projects, multiple scans may be required to get defaults set properly. The `REQUIRES_MODULES`, `REQUEST_MODULES`, and `UNRECOGNIZED_MODULES` arguments are meant to deal with this case. As an example, imagine a project with its source code, third party dependencies, as well as some utility modules which should only be built as necessary. Here, the project would perform three scans, one for each "grouping" of modules: ~~~{.cmake} # Scan our modules first because we need to know what of the other groups we # need. vtk_module_find_modules(our_modules "${CMAKE_CURRENT_SOURCE_DIR}/src") vtk_module_scan( MODULE_FILES ${our_modules} PROVIDES_MODULES our_enabled_modules REQUIRES_MODULES required_modules) # Scan the third party modules, requesting only those that are necessary, but # allowing them to be toggled during the build. vtk_module_find_modules(third_party_modules "${CMAKE_CURRENT_SOURCE_DIR}/third-party") vtk_module_scan( MODULE_FILES ${third_party_modules} PROVIDES_MODULES third_party_enabled_modules # These modules were requested by an earlier scan. REQUEST_MODULES ${required_modules} REQUIRES_MODULES required_modules UNRECOGNIZED_MODULES unrecognized_modules) # These modules are internal and should only be built if necessary. There is no # need to support them being enabled independently, so hide them from the # cache. vtk_module_find_modules(utility_modules "${CMAKE_CURRENT_SOURCE_DIR}/utilities") vtk_module_scan( MODULE_FILES ${utility_modules} PROVIDES_MODULES utility_enabled_modules # These modules were either requested or unrecognized by an earlier scan. REQUEST_MODULES ${required_modules} ${unrecognized_modules} REQUIRES_MODULES required_modules UNRECOGNIZED_MODULES unrecognized_modules HIDE_MODULES_FROM_CACHE ON) if (required_modules OR unrecognized_modules) # Not all of the modules we required were found. This should probably error out. endif () ~~~ #]==] function (vtk_module_scan) cmake_parse_arguments(PARSE_ARGV 0 _vtk_scan "" "WANT_BY_DEFAULT;HIDE_MODULES_FROM_CACHE;PROVIDES_MODULES;REQUIRES_MODULES;UNRECOGNIZED_MODULES;ENABLE_TESTS;PROVIDES_KITS" "MODULE_FILES;KIT_FILES;REQUEST_MODULES;REJECT_MODULES") if (_vtk_scan_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_scan: " "${_vtk_scan_UNPARSED_ARGUMENTS}") endif () if (NOT DEFINED _vtk_scan_WANT_BY_DEFAULT) set(_vtk_scan_WANT_BY_DEFAULT OFF) endif () if (NOT DEFINED _vtk_scan_HIDE_MODULES_FROM_CACHE) set(_vtk_scan_HIDE_MODULES_FROM_CACHE OFF) endif () if (NOT DEFINED _vtk_scan_PROVIDES_MODULES) message(FATAL_ERROR "The `PROVIDES_MODULES` argument is required.") endif () if (NOT DEFINED _vtk_scan_PROVIDES_KITS AND _vtk_scan_KIT_FILES) message(FATAL_ERROR "The `PROVIDES_KITS` argument is required.") endif () if (NOT DEFINED _vtk_scan_ENABLE_TESTS) set(_vtk_scan_ENABLE_TESTS "DEFAULT") endif () if (NOT (_vtk_scan_ENABLE_TESTS STREQUAL "ON" OR _vtk_scan_ENABLE_TESTS STREQUAL "OFF" OR _vtk_scan_ENABLE_TESTS STREQUAL "WANT" OR _vtk_scan_ENABLE_TESTS STREQUAL "DEFAULT")) message(FATAL_ERROR "The `ENABLE_TESTS` argument must be one of `ON`, `OFF`, `WANT`, or " "`DEFAULT`. " "Received `${_vtk_scan_ENABLE_TESTS}`.") endif () if (NOT _vtk_scan_MODULE_FILES) message(FATAL_ERROR "No module files given to scan.") endif () set(_vtk_scan_option_default_type STRING) if (_vtk_scan_HIDE_MODULES_FROM_CACHE) set(_vtk_scan_option_default_type INTERNAL) endif () set(_vtk_scan_all_kits) foreach (_vtk_scan_kit_file IN LISTS _vtk_scan_KIT_FILES) if (NOT IS_ABSOLUTE "${_vtk_scan_kit_file}") string(PREPEND _vtk_scan_kit_file "${CMAKE_CURRENT_SOURCE_DIR}/") endif () set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_vtk_scan_kit_file}") file(READ "${_vtk_scan_kit_file}" _vtk_scan_kit_args) # Replace comments. string(REGEX REPLACE "#[^\n]*\n" "\n" _vtk_scan_kit_args "${_vtk_scan_kit_args}") # Use argument splitting. string(REGEX REPLACE "( |\n)+" ";" _vtk_scan_kit_args "${_vtk_scan_kit_args}") _vtk_module_parse_kit_args(_vtk_scan_kit_name ${_vtk_scan_kit_args}) _vtk_module_debug(kit "@_vtk_scan_kit_name@ declared by @_vtk_scan_kit_file@") list(APPEND _vtk_scan_all_kits "${_vtk_scan_kit_name}") # Set properties for building. set_property(GLOBAL PROPERTY "_vtk_kit_${_vtk_scan_kit_name}_namespace" "${${_vtk_scan_kit_name}_NAMESPACE}") set_property(GLOBAL PROPERTY "_vtk_kit_${_vtk_scan_kit_name}_target_name" "${${_vtk_scan_kit_name}_TARGET_NAME}") set_property(GLOBAL PROPERTY "_vtk_kit_${_vtk_scan_kit_name}_library_name" "${${_vtk_scan_kit_name}_LIBRARY_NAME}") endforeach () set(_vtk_scan_all_modules) set(_vtk_scan_all_groups) set(_vtk_scan_rejected_modules) # Read all of the module files passed in. foreach (_vtk_scan_module_file IN LISTS _vtk_scan_MODULE_FILES) if (NOT IS_ABSOLUTE "${_vtk_scan_module_file}") string(PREPEND _vtk_scan_module_file "${CMAKE_CURRENT_SOURCE_DIR}/") endif () set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_vtk_scan_module_file}") file(READ "${_vtk_scan_module_file}" _vtk_scan_module_args) # Replace comments. string(REGEX REPLACE "#[^\n]*\n" "\n" _vtk_scan_module_args "${_vtk_scan_module_args}") # Use argument splitting. string(REGEX REPLACE "( |\n)+" ";" _vtk_scan_module_args "${_vtk_scan_module_args}") _vtk_module_parse_module_args(_vtk_scan_module_name ${_vtk_scan_module_args}) _vtk_module_debug(module "@_vtk_scan_module_name@ declared by @_vtk_scan_module_file@") string(REPLACE "::" "_" _vtk_scan_module_name_safe "${_vtk_scan_module_name}") if (${_vtk_scan_module_name}_THIRD_PARTY) if (_vtk_module_warnings) if (${_vtk_scan_module_name}_EXCLUDE_WRAP) message(WARNING "The third party ${_vtk_scan_module_name} module does not need to " "declare `EXCLUDE_WRAP` also.") endif () endif () if (${_vtk_scan_module_name}_IMPLEMENTABLE) message(FATAL_ERROR "The third party ${_vtk_scan_module_name} module may not be " "`IMPLEMENTABLE`.") endif () if (${_vtk_scan_module_name}_IMPLEMENTS) message(FATAL_ERROR "The third party ${_vtk_scan_module_name} module may not " "`IMPLEMENTS` another module.") endif () if (${_vtk_scan_module_name}_KIT) message(FATAL_ERROR "The third party ${_vtk_scan_module_name} module may not be part of " "a kit (${${_vtk_scan_module_name}_KIT}).") endif () endif () if (${_vtk_scan_module_name}_KIT) if (NOT ${_vtk_scan_module_name}_KIT IN_LIST _vtk_scan_all_kits) message(FATAL_ERROR "The ${_vtk_scan_module_name} belongs to the " "${${_vtk_scan_module_name}_KIT} kit, but it has not been scanned.") endif () endif () # Check if the module is visible. Modules which have a failing condition # are basically invisible. if (DEFINED ${_vtk_scan_module_name}_CONDITION) if (NOT (${${_vtk_scan_module_name}_CONDITION})) if (DEFINED "VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}") set_property(CACHE "VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}" PROPERTY TYPE INTERNAL) endif () _vtk_module_debug(module "@_vtk_scan_module_name@ hidden by its `CONDITION`") continue () endif () endif () # Determine whether we should provide a user-visible option for this # module. set(_vtk_build_use_option 1) if (DEFINED _vtk_scan_REQUEST_MODULE) if (_vtk_scan_module_name IN_LIST _vtk_scan_REQUEST_MODULE) set("_vtk_scan_enable_${_vtk_scan_module_name}" YES) set(_vtk_build_use_option 0) endif () endif () if (DEFINED _vtk_scan_REJECT_MODULES) if (_vtk_scan_module_name IN_LIST _vtk_scan_REJECT_MODULES) if (NOT _vtk_build_use_option) message(FATAL_ERROR "The ${_vtk_scan_module_name} module has been requested and rejected.") endif () # Rejected modules should not have a build option. set(_vtk_build_use_option 0) list(APPEND _vtk_scan_rejected_modules "${_vtk_scan_module_name}") endif () endif () # Handle cache entries and determine the enabled state of the module from # the relevant cache variables. if (_vtk_build_use_option) set("VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}" "DEFAULT" CACHE STRING "Enable the ${_vtk_scan_module_name} module. ${${_vtk_scan_module_name}_DESCRIPTION}") mark_as_advanced("VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}") set_property(CACHE "VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}" PROPERTY STRINGS "YES;WANT;DONT_WANT;NO;DEFAULT") _vtk_module_verify_enable_value("VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}") if (NOT VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe} STREQUAL "DEFAULT") set("_vtk_scan_enable_${_vtk_scan_module_name}" "${VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}}") set("_vtk_scan_enable_reason_${_vtk_scan_module_name}" "via `VTK_MDDULE_ENABLE_${_vtk_scan_module_name_safe}`") _vtk_module_debug(enable "@_vtk_scan_module_name@ is `${_vtk_scan_enable_${_vtk_scan_module_name}}` by cache value") endif () # Check the state of any groups the module belongs to. foreach (_vtk_scan_group IN LISTS "${_vtk_scan_module_name}_GROUPS") if (NOT DEFINED "VTK_GROUP_ENABLE_${_vtk_scan_group}") set(_vtk_scan_group_default "DEFAULT") if (DEFINED "_vtk_module_group_default_${_vtk_scan_group}") set(_vtk_scan_group_default "${_vtk_module_group_default_${_vtk_scan_group}}") endif () set("VTK_GROUP_ENABLE_${_vtk_scan_group}" "${_vtk_scan_group_default}" CACHE STRING "Enable the ${_vtk_scan_group} group modules.") set_property(CACHE "VTK_GROUP_ENABLE_${_vtk_scan_group}" PROPERTY STRINGS "YES;WANT;DONT_WANT;NO;DEFAULT") set_property(CACHE "VTK_GROUP_ENABLE_${_vtk_scan_group}" PROPERTY TYPE "${_vtk_scan_option_default_type}") endif () _vtk_module_verify_enable_value("VTK_GROUP_ENABLE_${_vtk_scan_group}") if (NOT VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe} STREQUAL "DEFAULT") continue () endif () # Determine the state of the group. set(_vtk_scan_group_enable "${VTK_GROUP_ENABLE_${_vtk_scan_group}}") if (NOT _vtk_scan_group_enable STREQUAL "DEFAULT") set("_vtk_scan_enable_${_vtk_scan_module_name}" "${_vtk_scan_group_enable}") set("_vtk_scan_enable_reason_${_vtk_scan_module_name}" "via `VTK_GROUP_ENABLE_${_vtk_scan_group}`") _vtk_module_debug(enable "@_vtk_scan_module_name@ is DEFAULT, using group `@_vtk_scan_group@` setting: @_vtk_scan_group_enable@") endif () endforeach () set_property(CACHE "VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe}" PROPERTY TYPE "${_vtk_scan_option_default_type}") endif () if (NOT DEFINED "_vtk_scan_enable_${_vtk_scan_module_name}" AND VTK_MODULE_ENABLE_${_vtk_scan_module_name_safe} STREQUAL "DEFAULT") if (_vtk_scan_WANT_BY_DEFAULT) set("_vtk_scan_enable_${_vtk_scan_module_name}" "WANT") else () set("_vtk_scan_enable_${_vtk_scan_module_name}" "DONT_WANT") endif () if (DEFINED _vtk_module_reason_WANT_BY_DEFAULT) set("_vtk_scan_enable_reason_${_vtk_scan_module_name}" "${_vtk_module_reason_WANT_BY_DEFAULT}") else () set("_vtk_scan_enable_reason_${_vtk_scan_module_name}" "via `WANT_BY_DEFAULT=${_vtk_scan_WANT_BY_DEFAULT}`") endif () _vtk_module_debug(enable "@_vtk_scan_module_name@ is DEFAULT, using `WANT_BY_DEFAULT`: ${_vtk_scan_enable_reason_${_vtk_scan_module_name}}") endif () list(APPEND _vtk_scan_all_modules "${_vtk_scan_module_name}") set("_vtk_scan_${_vtk_scan_module_name}_all_depends" ${${_vtk_scan_module_name}_DEPENDS} ${${_vtk_scan_module_name}_PRIVATE_DEPENDS}) if (${_vtk_scan_module_name}_THIRD_PARTY) set("${_vtk_scan_module_name}_EXCLUDE_WRAP" TRUE) set("${_vtk_scan_module_name}_IMPLEMENTABLE" FALSE) set("${_vtk_scan_module_name}_IMPLEMENTS") endif () if (${_vtk_scan_module_name}_KIT) _vtk_module_debug(kit "@_vtk_scan_module_name@ belongs to the ${${_vtk_scan_module_name}_KIT} kit") endif () # Set properties for building. set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_file" "${_vtk_scan_module_file}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_namespace" "${${_vtk_scan_module_name}_NAMESPACE}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_target_name" "${${_vtk_scan_module_name}_TARGET_NAME}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_library_name" "${${_vtk_scan_module_name}_LIBRARY_NAME}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_third_party" "${${_vtk_scan_module_name}_THIRD_PARTY}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_exclude_wrap" "${${_vtk_scan_module_name}_EXCLUDE_WRAP}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_kit" "${${_vtk_scan_module_name}_KIT}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_depends" "${${_vtk_scan_module_name}_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_order_depends" "${${_vtk_scan_module_name}_ORDER_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_private_depends" "${${_vtk_scan_module_name}_PRIVATE_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_optional_depends" "${${_vtk_scan_module_name}_OPTIONAL_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_test_depends" "${${_vtk_scan_module_name}_TEST_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_test_optional_depends" "${${_vtk_scan_module_name}_TEST_OPTIONAL_DEPENDS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_test_labels" "${${_vtk_scan_module_name}_TEST_LABELS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_implements" "${${_vtk_scan_module_name}_IMPLEMENTS}") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_implementable" "${${_vtk_scan_module_name}_IMPLEMENTABLE}") # create absolute path for license files set(_license_files) foreach (_license_file IN LISTS ${_vtk_scan_module_name}_LICENSE_FILES) if (NOT IS_ABSOLUTE "${_license_file}") get_filename_component(_vtk_scan_module_dir "${_vtk_scan_module_file}" DIRECTORY) string(PREPEND _license_file "${_vtk_scan_module_dir}/") endif () list(APPEND _license_files "${_license_file}") endforeach () set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_license_files" "${_license_files}") if (_vtk_scan_ENABLE_TESTS STREQUAL "WANT") set_property(GLOBAL PROPERTY "_vtk_module_${_vtk_scan_module_name}_enable_tests_by_want" "1") endif () endforeach () set(_vtk_scan_current_modules "${_vtk_scan_all_modules}") vtk_topological_sort(_vtk_scan_all_modules "_vtk_scan_" "_all_depends") set(_vtk_scan_provided_modules) set(_vtk_scan_required_modules) set(_vtk_scan_disabled_modules) # Seed the `_vtk_scan_provide_` variables with modules requested and rejected # as arguments. foreach (_vtk_scan_request_module IN LISTS _vtk_scan_REQUEST_MODULES) set("_vtk_scan_provide_${_vtk_scan_request_module}" ON) if (DEFINED "_vtk_module_reason_${_vtk_scan_request_module}") set("_vtk_scan_provide_reason_${_vtk_scan_request_module}" "${_vtk_module_reason_${_vtk_scan_request_module}}") else () set("_vtk_scan_provide_reason_${_vtk_scan_request_module}" "via `REQUEST_MODULES`") endif () _vtk_module_debug(provide "@_vtk_scan_request_module@ is provided ${_vtk_scan_provide_reason_${_vtk_scan_request_module}}") endforeach () foreach (_vtk_scan_reject_module IN LISTS _vtk_scan_REJECT_MODULES) set("_vtk_scan_provide_${_vtk_scan_reject_module}" OFF) if (DEFINED "_vtk_module_reason_${_vtk_scan_reject_module}") set("_vtk_scan_provide_reason_${_vtk_scan_reject_module}" "${_vtk_module_reason_${_vtk_scan_reject_module}}") else () set("_vtk_scan_provide_reason_${_vtk_scan_reject_module}" "via `REJECT_MODULES`") endif () _vtk_module_debug(provide "@_vtk_scan_reject_module@ is not provided ${_vtk_scan_provide_reason_${_vtk_scan_reject_module}}") endforeach () # Traverse the graph classifying the quad-state for enabling modules into a # boolean stored in the `_vtk_scan_provide_` variables. foreach (_vtk_scan_module IN LISTS _vtk_scan_all_modules) if (NOT _vtk_scan_module IN_LIST _vtk_scan_current_modules) _vtk_module_debug(provide "@_vtk_scan_module@ is ignored because it is not in the current scan set") continue () endif () if (DEFINED "_vtk_scan_provide_${_vtk_scan_module}") # Already done. elseif (_vtk_scan_enable_${_vtk_scan_module} STREQUAL "YES") # Mark enabled modules as to-be-provided. Any errors with requiring a # disabled module will be dealt with later. set("_vtk_scan_provide_${_vtk_scan_module}" ON) set("_vtk_scan_provide_reason_${_vtk_scan_module}" "via a `YES` setting (${_vtk_scan_enable_reason_${_vtk_scan_module}})") _vtk_module_debug(provide "@_vtk_scan_module@ is provided due to `YES` setting") elseif (_vtk_scan_enable_${_vtk_scan_module} STREQUAL "WANT") # Check to see if we can provide this module by checking of any of its # dependencies have been disabled. set(_vtk_scan_test_depends) if (NOT ${_vtk_scan_module}_THIRD_PARTY AND _vtk_scan_ENABLE_TESTS STREQUAL "ON") # If the tests have to be on, we also need the test dependencies. set(_vtk_scan_test_depends "${${_vtk_scan_module}_TEST_DEPENDS}") endif () set("_vtk_scan_provide_${_vtk_scan_module}" ON) set("_vtk_scan_provide_reason_${_vtk_scan_module}" "via a `WANT` setting (${_vtk_scan_enable_reason_${_vtk_scan_module}})") _vtk_module_debug(provide "@_vtk_scan_module@ is provided due to `WANT` setting") foreach (_vtk_scan_module_depend IN LISTS "${_vtk_scan_module}_DEPENDS" "${_vtk_scan_module}_PRIVATE_DEPENDS" _vtk_scan_test_depends) if (DEFINED "_vtk_scan_provide_${_vtk_scan_module_depend}" AND NOT _vtk_scan_provide_${_vtk_scan_module_depend}) set("_vtk_scan_provide_${_vtk_scan_module}" OFF) set("_vtk_scan_provide_reason_${_vtk_scan_module}" "due to the ${_vtk_scan_module_depend} module not being available") if (DEFINED "_vtk_scan_provide_reason_${_vtk_scan_module_depend}") string(APPEND "_vtk_scan_provide_reason_${_vtk_scan_module}" " (${_vtk_scan_provide_reason_${_vtk_scan_module_depend}})") endif () _vtk_module_debug(provide "@_vtk_scan_module@ is not provided due to not provided dependency @_vtk_scan_module_depend@") break () endif () endforeach () elseif (_vtk_scan_enable_${_vtk_scan_module} STREQUAL "DONT_WANT") # Check for disabled dependencies and disable if so. foreach (_vtk_scan_module_depend IN LISTS "${_vtk_scan_module}_DEPENDS" "${_vtk_scan_module}_PRIVATE_DEPENDS" _vtk_scan_test_depends) if (DEFINED "_vtk_scan_provide_${_vtk_scan_module_depend}" AND NOT _vtk_scan_provide_${_vtk_scan_module_depend}) set("_vtk_scan_provide_${_vtk_scan_module}" OFF) set("_vtk_scan_provide_reason_${_vtk_scan_module}" "due to the ${_vtk_scan_module_depend} module not being available") if (DEFINED "_vtk_scan_provide_reason_${_vtk_scan_module_depend}") string(APPEND "_vtk_scan_provide_reason_${_vtk_scan_module}" " (${_vtk_scan_provide_reason_${_vtk_scan_module_depend}})") endif () _vtk_module_debug(provide "@_vtk_scan_module@ is not provided due to not provided dependency @_vtk_scan_module_depend@") break () endif () endforeach () elseif (_vtk_scan_enable_${_vtk_scan_module} STREQUAL "NO") # Disable the module. set("_vtk_scan_provide_${_vtk_scan_module}" OFF) set("_vtk_scan_provide_reason_${_vtk_scan_module}" "via a `NO` setting (${_vtk_scan_enable_reason_${_vtk_scan_module}})") _vtk_module_debug(provide "@_vtk_scan_module@ is not provided due to `NO` setting") endif () # Collect disabled modules into a list. if (DEFINED "_vtk_scan_provide_${_vtk_scan_module}" AND NOT _vtk_scan_provide_${_vtk_scan_module}) list(APPEND _vtk_scan_disabled_modules "${_vtk_scan_module}") endif () if (NOT DEFINED "_vtk_scan_provide_${_vtk_scan_module}") _vtk_module_debug(provide "@_vtk_scan_module@ is indeterminate (${_vtk_scan_enable_${_vtk_scan_module}})") endif () endforeach () # Scan all modules from the top of tree to the bottom. list(REVERSE _vtk_scan_all_modules) foreach (_vtk_scan_module IN LISTS _vtk_scan_all_modules) if (NOT _vtk_scan_module IN_LIST _vtk_scan_current_modules) continue () endif () # If we're providing this module... if (_vtk_scan_provide_${_vtk_scan_module}) list(APPEND _vtk_scan_provided_modules "${_vtk_scan_module}") # Grab any test dependencies that are required. set(_vtk_scan_test_depends) set(_vtk_scan_test_wants) if (NOT ${_vtk_scan_module}_THIRD_PARTY) if (_vtk_scan_ENABLE_TESTS STREQUAL "ON") set_property(GLOBAL APPEND PROPERTY "_vtk_module_test_modules" "${_vtk_scan_module}") set(_vtk_scan_test_depends "${${_vtk_scan_module}_TEST_DEPENDS}") elseif (_vtk_scan_ENABLE_TESTS STREQUAL "WANT") set_property(GLOBAL APPEND PROPERTY "_vtk_module_test_modules" "${_vtk_scan_module}") set(_vtk_scan_test_wants _vtk_scan_wants_marker ${${_vtk_scan_module}_TEST_DEPENDS}) elseif (_vtk_scan_ENABLE_TESTS STREQUAL "DEFAULT") set_property(GLOBAL APPEND PROPERTY "_vtk_module_test_modules" "${_vtk_scan_module}") elseif (_vtk_scan_ENABLE_TESTS STREQUAL "OFF") # Nothing to do. else () message(FATAL_ERROR "Unrecognized option for ENABLE_TESTS: ${_vtk_module_ENABLE_TESTS}.") endif () endif () # Add all dependent modules to the list of required or provided modules. set(_vtk_scan_is_wanting 0) foreach (_vtk_scan_module_depend IN LISTS "${_vtk_scan_module}_DEPENDS" "${_vtk_scan_module}_PRIVATE_DEPENDS" _vtk_scan_test_depends _vtk_scan_test_wants) if (_vtk_scan_module_depend STREQUAL "_vtk_scan_wants_marker") set(_vtk_scan_is_wanting 1) continue () endif () # Though we need to error if this would cause a disabled module to be # provided. if (_vtk_scan_module_depend IN_LIST _vtk_scan_disabled_modules) if (_vtk_scan_is_wanting) continue () else () message(FATAL_ERROR "The ${_vtk_scan_module} module (enabled " "${_vtk_scan_provide_reason_${_vtk_scan_module}}) requires the " "disabled module ${_vtk_scan_module_depend} (disabled " "${_vtk_scan_provide_reason_${_vtk_scan_module_depend}}).") endif () endif () if (DEFINED "_vtk_scan_provide_${_vtk_scan_module_depend}") if (NOT _vtk_scan_provide_${_vtk_scan_module_depend}) message(FATAL_ERROR "The ${_vtk_scan_module_depend} module (disabled " "${_vtk_scan_provide_reason_${_vtk_scan_module_depend}}) should " "be provided because it is required by ${_vtk_scan_module} " "(${_vtk_scan_provide_reason_${_vtk_scan_module}})") endif () continue () endif () set("_vtk_scan_provide_reason_${_vtk_scan_module_depend}" "via dependency from ${_vtk_scan_module}") if (DEFINED "_vtk_scan_provide_reason_${_vtk_scan_module}") string(APPEND "_vtk_scan_provide_reason_${_vtk_scan_module_depend}" " (${_vtk_scan_provide_reason_${_vtk_scan_module}})") endif () set("_vtk_scan_provide_${_vtk_scan_module_depend}" ON) if (NOT _vtk_scan_module_depend IN_LIST _vtk_scan_current_modules) if (NOT TARGET "${_vtk_scan_module_depend}") _vtk_module_debug(provide "@_vtk_scan_module_depend@ is external and required due to dependency from @_vtk_scan_module@") endif () list(APPEND _vtk_scan_required_modules "${_vtk_scan_module_depend}") else () _vtk_module_debug(provide "@_vtk_scan_module_depend@ is provided due to dependency from @_vtk_scan_module@") list(APPEND _vtk_scan_provided_modules "${_vtk_scan_module_depend}") endif () endforeach () endif () endforeach () if (_vtk_scan_provided_modules) list(REMOVE_DUPLICATES _vtk_scan_provided_modules) endif () set(_vtk_scan_provided_kits) # Build a list of kits which contain the provided modules. foreach (_vtk_scan_provided_module IN LISTS _vtk_scan_provided_modules) if (${_vtk_scan_provided_module}_KIT) list(APPEND _vtk_scan_provided_kits "${${_vtk_scan_provided_module}_KIT}") set_property(GLOBAL APPEND PROPERTY "_vtk_kit_${${_vtk_scan_provided_module}_KIT}_kit_modules" "${_vtk_scan_provided_module}") endif () endforeach () if (_vtk_scan_provided_kits) list(REMOVE_DUPLICATES _vtk_scan_provided_kits) endif () if (_vtk_scan_required_modules) list(REMOVE_DUPLICATES _vtk_scan_required_modules) endif () set(_vtk_scan_unrecognized_modules ${_vtk_scan_REQUEST_MODULES} ${_vtk_scan_REJECT_MODULES}) if (_vtk_scan_unrecognized_modules AND (_vtk_scan_provided_modules OR _vtk_scan_rejected_modules)) list(REMOVE_ITEM _vtk_scan_unrecognized_modules ${_vtk_scan_provided_modules} ${_vtk_scan_rejected_modules}) endif () set("${_vtk_scan_PROVIDES_MODULES}" ${_vtk_scan_provided_modules} PARENT_SCOPE) if (DEFINED _vtk_scan_REQUIRES_MODULES) set("${_vtk_scan_REQUIRES_MODULES}" ${_vtk_scan_required_modules} PARENT_SCOPE) endif () if (DEFINED _vtk_scan_UNRECOGNIZED_MODULES) set("${_vtk_scan_UNRECOGNIZED_MODULES}" ${_vtk_scan_unrecognized_modules} PARENT_SCOPE) endif () if (DEFINED _vtk_scan_PROVIDES_KITS) set("${_vtk_scan_PROVIDES_KITS}" ${_vtk_scan_provided_kits} PARENT_SCOPE) endif () endfunction () #[==[ @page module-overview @section module-target-functions Module-as-target functions Due to the nature of VTK modules supporting being built as kits, the module name might not be usable as a target to CMake's `target_` family of commands. Instead, there are various wrappers around them which take the module name as an argument. These handle the forwarding of relevant information to the kit library as well where necessary. - @ref vtk_module_set_properties - @ref vtk_module_set_property - @ref vtk_module_get_property - @ref vtk_module_depend - @ref vtk_module_include - @ref vtk_module_definitions - @ref vtk_module_compile_options - @ref vtk_module_compile_features - @ref vtk_module_link - @ref vtk_module_link_options #]==] #[==[ @page module-internal-api @section module-target-internals Module target internals When manipulating modules as targets, there are a few functions provided for use in wrapping code to more easily access them. - @ref _vtk_module_real_target - @ref _vtk_module_real_target_kit #]==] #[==[ @ingroup module-internal @brief The real target for a module ~~~ _vtk_module_real_target( ) ~~~ Sometimes the actual, core target for a module is required (e.g., setting CMake-level target properties or install rules). This function returns the real target for a module. #]==] function (_vtk_module_real_target var module) if (ARGN) message(FATAL_ERROR "Unparsed arguments for _vtk_module_real_target: ${ARGN}.") endif () set(_vtk_real_target_res "") if (TARGET "${module}") get_property(_vtk_real_target_imported TARGET "${module}" PROPERTY IMPORTED) if (_vtk_real_target_imported) set(_vtk_real_target_res "${module}") endif () endif () if (NOT _vtk_real_target_res) get_property(_vtk_real_target_res GLOBAL PROPERTY "_vtk_module_${module}_target_name") # Querying during the build. if (DEFINED _vtk_build_BUILD_WITH_KITS AND _vtk_build_BUILD_WITH_KITS) get_property(_vtk_real_target_kit GLOBAL PROPERTY "_vtk_module_${module}_kit") if (_vtk_real_target_kit) string(APPEND _vtk_real_target_res "-objects") endif () # A query for after the module is built. elseif (TARGET "${_vtk_real_target_res}-objects") string(APPEND _vtk_real_target_res "-objects") endif () endif () if (NOT _vtk_real_target_res) set(_vtk_real_target_msg "") if (NOT TARGET "${module}") if (DEFINED _vtk_build_module) set(_vtk_real_target_msg " Is a module dependency missing?") elseif (TARGET "${module}") set(_vtk_real_target_msg " It's a target, but is it a VTK module?") else () set(_vtk_real_target_msg " The module name is not a CMake target. Is there a typo? Is it missing a `Package::` prefix? Is a `find_package` missing a required component?") endif () endif () message(FATAL_ERROR "Failed to determine the real target for the `${module}` " "module.${_vtk_real_target_msg}") endif () set("${var}" "${_vtk_real_target_res}" PARENT_SCOPE) endfunction () #[==[ @ingroup module-internal @brief The real target for a kit ~~~ _vtk_module_real_target_kit( ) ~~~ Sometimes the actual, core target for a module is required (e.g., setting CMake-level target properties or install rules). This function returns the real target for a kit. #]==] function (_vtk_module_real_target_kit var kit) if (ARGN) message(FATAL_ERROR "Unparsed arguments for _vtk_module_real_target_kit: ${ARGN}.") endif () set(_vtk_real_target_res "") if (TARGET "${kit}") get_property(_vtk_real_target_imported TARGET "${kit}" PROPERTY IMPORTED) if (_vtk_real_target_imported) set(_vtk_real_target_res "${kit}") endif () endif () if (NOT _vtk_real_target_res) get_property(_vtk_real_target_res GLOBAL PROPERTY "_vtk_kit_${kit}_target_name") endif () if (NOT _vtk_real_target_res) message(FATAL_ERROR "Failed to determine the real target for the `${kit}` kit.") endif () set("${var}" "${_vtk_real_target_res}" PARENT_SCOPE) endfunction () #[==[ @ingroup module @brief Set multiple properties on a module A wrapper around `set_target_properties` that works for modules. ~~~ vtk_module_set_properties( [ ]...) ~~~ #]==] function (vtk_module_set_properties module) _vtk_module_real_target(_vtk_set_properties_target "${module}") set_target_properties("${_vtk_set_properties_target}" PROPERTIES ${ARGN}) endfunction () #[==[ @ingroup module @brief Set a property on a module A wrapper around `set_property(TARGET)` that works for modules. ~~~ vtk_module_set_property( [APPEND] [APPEND_STRING] PROPERTY VALUE ...) ~~~ #]==] function (vtk_module_set_property module) cmake_parse_arguments(PARSE_ARGV 1 _vtk_property "APPEND;APPEND_STRING" "PROPERTY" "VALUE") if (_vtk_property_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_set_property: " "${_vtk_property_UNPARSED_ARGUMENTS}.") endif () if (NOT DEFINED _vtk_property_PROPERTY) message(FATAL_ERROR "The `PROPERTY` argument is required.") endif () if (NOT DEFINED _vtk_property_VALUE) message(FATAL_ERROR "The `VALUE` argument is required.") endif () if (_vtk_property_APPEND AND _vtk_property_APPEND_STRING) message(FATAL_ERROR "`APPEND` and `APPEND_STRING` may not be used at the same time.") endif () set(_vtk_property_args) if (_vtk_property_APPEND) list(APPEND _vtk_property_args APPEND) endif () if (_vtk_property_APPEND_STRING) list(APPEND _vtk_property_args APPEND_STRING) endif () _vtk_module_real_target(_vtk_property_target "${module}") set_property(TARGET "${_vtk_property_target}" ${_vtk_property_args} PROPERTY "${_vtk_property_PROPERTY}" "${_vtk_property_VALUE}") endfunction () #[==[ @ingroup module @brief Get a property from a module A wrapper around `get_property(TARGET)` that works for modules. ~~~ vtk_module_get_property( PROPERTY VARIABLE ) ~~~ The variable name passed to the `VARIABLE` argument will be unset if the property is not set (rather than the empty string). #]==] function (vtk_module_get_property module) cmake_parse_arguments(PARSE_ARGV 1 _vtk_property "" "PROPERTY;VARIABLE" "") if (_vtk_property_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_get_property: " "${_vtk_property_UNPARSED_ARGUMENTS}.") endif () if (NOT DEFINED _vtk_property_PROPERTY) message(FATAL_ERROR "The `PROPERTY` argument is required.") endif () if (NOT DEFINED _vtk_property_VARIABLE) message(FATAL_ERROR "The `VARIABLE` argument is required.") endif () _vtk_module_real_target(_vtk_property_target "${module}") get_property(_vtk_property_is_set TARGET "${_vtk_property_target}" PROPERTY "${_vtk_property_PROPERTY}" SET) if (_vtk_property_is_set) get_property(_vtk_property_value TARGET "${_vtk_property_target}" PROPERTY "${_vtk_property_PROPERTY}") set("${_vtk_property_VARIABLE}" "${_vtk_property_value}" PARENT_SCOPE) else () unset("${_vtk_property_VARIABLE}" PARENT_SCOPE) endif () endfunction () #[==[ @ingroup module-impl @brief Generate arguments for target function wrappers Create the `INTERFACE`, `PUBLIC`, and `PRIVATE` arguments for a function wrapping CMake's `target_` functions to call the wrapped function. This is necessary because not all of the functions support empty lists given a keyword. #]==] function (_vtk_module_target_function prefix) foreach (visibility IN ITEMS INTERFACE PUBLIC PRIVATE) if (${prefix}_${visibility}) set("${prefix}_${visibility}_args" "${visibility}" ${${prefix}_${visibility}} PARENT_SCOPE) endif () endforeach () endfunction () #[==[ @ingroup module @brief Add dependencies to a module A wrapper around `add_dependencies` that works for modules. ~~~ vtk_module_depend( ...) ~~~ #]==] function (vtk_module_depend module) _vtk_module_real_target(_vtk_depend_target "${module}") add_dependencies("${_vtk_depend_target}" ${ARGN}) endfunction () #[==[ @ingroup module @brief Add source files to a module A wrapper around `target_sources` that works for modules. ~~~ vtk_module_sources( [PUBLIC ...] [PRIVATE ...] [INTERFACE ...]) ~~~ #]==] function (vtk_module_sources module) cmake_parse_arguments(PARSE_ARGV 1 _vtk_sources "" "" "INTERFACE;PUBLIC;PRIVATE") if (_vtk_sources_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_sources: " "${_vtk_sources_UNPARSED_ARGUMENTS}.") endif () _vtk_module_real_target(_vtk_sources_target "${module}") _vtk_module_target_function(_vtk_sources) if (NOT _vtk_sources_INTERFACE_args AND NOT _vtk_sources_PUBLIC_args AND NOT _vtk_sources_PRIVATE_args) return () endif () target_sources("${_vtk_sources_target}" ${_vtk_sources_INTERFACE_args} ${_vtk_sources_PUBLIC_args} ${_vtk_sources_PRIVATE_args}) endfunction () #[==[ @ingroup module @brief Add include directories to a module A wrapper around `target_include_directories` that works for modules. ~~~ vtk_module_include( [SYSTEM] [PUBLIC ...] [PRIVATE ...] [INTERFACE ...]) ~~~ #]==] function (vtk_module_include module) cmake_parse_arguments(PARSE_ARGV 1 _vtk_include "SYSTEM" "" "INTERFACE;PUBLIC;PRIVATE") if (_vtk_include_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_include: " "${_vtk_include_UNPARSED_ARGUMENTS}.") endif () _vtk_module_real_target(_vtk_include_target "${module}") _vtk_module_target_function(_vtk_include) set(_vtk_include_system_arg) if (_vtk_include_SYSTEM) set(_vtk_include_system_arg SYSTEM) endif () if (NOT _vtk_include_INTERFACE_args AND NOT _vtk_include_PUBLIC_args AND NOT _vtk_include_PRIVATE_args) return () endif () target_include_directories("${_vtk_include_target}" ${_vtk_include_system_arg} ${_vtk_include_INTERFACE_args} ${_vtk_include_PUBLIC_args} ${_vtk_include_PRIVATE_args}) endfunction () #[==[ @ingroup module @brief Add compile definitions to a module A wrapper around `target_compile_definitions` that works for modules. ~~~ vtk_module_definitions( [PUBLIC ...] [PRIVATE ...] [INTERFACE ...]) ~~~ #]==] function (vtk_module_definitions module) cmake_parse_arguments(PARSE_ARGV 1 _vtk_definitions "" "" "INTERFACE;PUBLIC;PRIVATE") if (_vtk_definitions_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments for vtk_module_definitions: " "${_vtk_definitions_UNPARSED_ARGUMENTS}.") endif () _vtk_module_real_target(_vtk_definitions_target "${module}") _vtk_module_target_function(_vtk_definitions) if (NOT _vtk_definitions_INTERFACE_args AND NOT _vtk_definitions_PUBLIC_args AND NOT _vtk_definitions_PRIVATE_args) return () endif () target_compile_definitions("${_vtk_definitions_target}" ${_vtk_definitions_INTERFACE_args} ${_vtk_definitions_PUBLIC_args} ${_vtk_definitions_PRIVATE_args}) endfunction () #[==[ @ingroup module @brief Add compile options to a module A wrapper around `target_compile_options` that works for modules. ~~~ vtk_module_compile_options( [PUBLIC