From 0900298d466e819dd6d8fd39c0be333dc09af189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Fri, 3 May 2019 16:03:15 +0200 Subject: cmake: register plug-ins, create dependencies file This commit introduces infrastructure work to allow static builds of Qt to handle importing of plug-ins. Change-Id: Ife0ca3ca7276ea8ec96fe0eb6adf934fad7620ec Reviewed-by: Alexandru Croitor --- cmake/QtBuild.cmake | 158 +++++++++++++---- cmake/QtFeature.cmake | 5 +- cmake/QtModuleConfig.cmake.in | 6 +- cmake/QtModuleDependencies.cmake.in | 1 + cmake/QtPluginConfig.cmake.in | 13 ++ cmake/QtPluginDependencies.cmake.in | 53 ++++++ cmake/QtPostProcess.cmake | 342 +++++++++++++++++++++++------------- cmake/QtProperties.cmake | 8 + 8 files changed, 424 insertions(+), 162 deletions(-) create mode 100644 cmake/QtPluginConfig.cmake.in create mode 100644 cmake/QtPluginDependencies.cmake.in create mode 100644 cmake/QtProperties.cmake (limited to 'cmake') diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index ed6dba2dae..20b7c5bec8 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -119,9 +119,13 @@ endif() macro(qt_internal_set_qt_known_modules) set(QT_KNOWN_MODULES ${ARGN} CACHE INTERNAL "Known Qt modules" FORCE) endmacro() +macro(qt_internal_set_qt_known_plugins) + set(QT_KNOWN_PLUGINS ${ARGN} CACHE INTERNAL "Known Qt plugins" FORCE) +endmacro() # Reset: qt_internal_set_qt_known_modules("") +qt_internal_set_qt_known_plugins("") set(QT_KNOWN_MODULES_WITH_TOOLS "" CACHE INTERNAL "Known Qt modules with tools" FORCE) macro(qt_internal_append_known_modules_with_tools module) @@ -652,7 +656,8 @@ function(qt_internal_module_info result target) endfunction() -set(__default_private_args "SOURCES;LIBRARIES;INCLUDE_DIRECTORIES;DEFINES;DBUS_ADAPTOR_BASENAME;DBUS_ADAPTOR_FLAGS;DBUS_ADAPTOR_SOURCES;DBUS_INTERFACE_BASENAME;DBUS_INTERFACE_FLAGS;DBUS_INTERFACE_SOURCES;FEATURE_DEPENDENCIES;COMPILE_OPTIONS;LINK_OPTIONS;MOC_OPTIONS;DISABLE_AUTOGEN_TOOLS;ENABLE_AUTOGEN_TOOLS") +set(__default_private_args "SOURCES;LIBRARIES;INCLUDE_DIRECTORIES;DEFINES;DBUS_ADAPTOR_BASENAME;DBUS_ADAPTOR_FLAGS;DBUS_ADAPTOR_SOURCES;DBUS_INTERFACE_BASENAME;DBUS_INTERFACE_FLAGS;DBUS_INTERFACE_SOURCES;FEATURE_DEPENDENCIES;COMPILE_OPTIONS;LINK_OPTIONS;MOC_OPTIONS;DISABLE_AUTOGEN_TOOLS;ENABLE_AUTOGEN_TOOLS;PLUGIN_TYPES") + set(__default_public_args "PUBLIC_LIBRARIES;PUBLIC_INCLUDE_DIRECTORIES;PUBLIC_DEFINES;PUBLIC_COMPILE_OPTIONS;PUBLIC_LINK_OPTIONS") @@ -715,6 +720,32 @@ function(qt_autogen_tools target) endif() endfunction() +# This function stores the list of Qt modules a library depend on, +# along with their version info, for usage in ${target}Depends.cmake file +function(qt_register_target_dependencies target public_libs private_libs) + get_target_property(target_deps "${target}" _qt_target_deps) + if(NOT target_deps) + set(target_deps "") + endif() + + # TODO: should this also be in extend_target ? From the looks of it I would say that + # it is not necessary but I'm not sure + foreach(lib IN LISTS public_libs private_libs) + if ("${lib}" MATCHES "^Qt::(.*)") + set(lib "${CMAKE_MATCH_1}") + if (lib STREQUAL Platform OR lib STREQUAL GlobalConfig) + list(APPEND target_deps "Qt5\;${PROJECT_VERSION}") + elseif ("${lib}" MATCHES "(.*)Private") + list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${CMAKE_MATCH_1}\;${PROJECT_VERSION}") + else() + list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}") + endif() + endif() + endforeach() + + set_target_properties("${target}" PROPERTIES _qt_target_deps "${target_deps}") +endfunction() + # This function can be used to add sources/libraries/etc. to the specified CMake target # if the provided CONDITION evaluates to true. function(extend_target target) @@ -1003,6 +1034,11 @@ function(add_qt_module target) set_property(TARGET "${target}" APPEND PROPERTY PRIVATE_HEADER "${module_headers_private}") endif() + # Plugin types associated to a module + if(NOT "x${arg_PLUGIN_TYPES}" STREQUAL "x") + set_target_properties("${target}" PROPERTIES MODULE_PLUGIN_TYPES "${arg_PLUGIN_TYPES}") + endif() + set_target_properties("${target}" PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}" RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}" @@ -1121,15 +1157,15 @@ function(add_qt_module target) list(APPEND extra_cmake_includes "${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake") endif() - set(extra_cmake_code "") + set(extra_cmake_code "") - if(target STREQUAL Core) - # Propagate non-build related variables that are needed for consuming Qt packages. - # Do this in CoreConfig instead of Qt5Config, so that consumers can also use - # find_package(Qt5Core) instead of find_package(Qt5 COMPONENTS Core) - string(APPEND extra_cmake_code " + if(target STREQUAL Core) + # Propagate non-build related variables that are needed for consuming Qt packages. + # Do this in CoreConfig instead of Qt5Config, so that consumers can also use + # find_package(Qt5Core) instead of find_package(Qt5 COMPONENTS Core) + string(APPEND extra_cmake_code " set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})") - endif() + endif() configure_package_config_file( "${QT_CMAKE_DIR}/QtModuleConfig.cmake.in" @@ -1137,7 +1173,7 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})") INSTALL_DESTINATION "${config_install_dir}" ) write_basic_package_version_file( - ${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersion.cmake + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion ) @@ -1198,27 +1234,7 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})") $ ) - get_target_property(target_deps "${target}" _qt_target_deps) - if(NOT target_deps) - set(target_deps "") - endif() - - # TODO: should this also be in extend_target ? From the looks of it I would say that - # it is not necessary but I'm not sure - foreach(lib IN LISTS arg_PUBLIC_LIBRARIES qt_libs_private) - if ("${lib}" MATCHES "^Qt::(.*)") - set(lib "${CMAKE_MATCH_1}") - if (lib STREQUAL Platform OR lib STREQUAL GlobalConfig) - list(APPEND target_deps "Qt5\;${PROJECT_VERSION}") - elseif ("${lib}" MATCHES "(.*)Private") - list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${CMAKE_MATCH_1}\;${PROJECT_VERSION}") - else() - list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}") - endif() - endif() - endforeach() - - set_target_properties("${target}" PROPERTIES _qt_target_deps "${target_deps}") + qt_register_target_dependencies("${target}" "${arg_PUBLIC_LIBRARIES}" "${qt_libs_private}") if(NOT ${arg_DISABLE_TOOLS_EXPORT}) qt_export_tools(${target}) @@ -1299,18 +1315,41 @@ function(qt_internal_check_directory_or_type name dir type default result_var) endif() endfunction() +# Utility function to find the module to which a plug-in belongs. +# This will set the QT_MODULE target property on the plug-in - e.g. "Gui", "Sql"... +function(qt_get_module_for_plugin target target_type) + foreach(qt_module ${QT_KNOWN_MODULES}) + get_target_property(plugin_types "${qt_module}" MODULE_PLUGIN_TYPES) + if(plugin_types) + foreach(plugin_type ${plugin_types}) + if("${target_type}" STREQUAL "${plugin_type}") + set_target_properties("${target}" PROPERTIES QT_MODULE "${qt_module}") + return() + endif() + endforeach() + endif() + endforeach() + message(AUTHOR_WARNING "The plug-in '${target}' does not belong to any Qt module.") +endfunction() + # This is the main entry point for defining Qt plugins. # A CMake target is created with the given target. The TYPE parameter is needed to place the # plugin into the correct plugins/ sub-directory. function(add_qt_plugin target) qt_internal_module_info(module "${target}") + qt_internal_set_qt_known_plugins("${QT_KNOWN_PLUGINS}" "${target}") + qt_parse_all_arguments(arg "add_qt_plugin" "STATIC" - "TYPE;OUTPUT_DIRECTORY;INSTALL_DIRECTORY;ARCHIVE_INSTALL_DIRECTORY" + "TYPE;CLASS_NAME;OUTPUT_DIRECTORY;INSTALL_DIRECTORY;ARCHIVE_INSTALL_DIRECTORY" "${__default_private_args};${__default_public_args}" ${ARGN}) set(output_directory_default "${QT_BUILD_DIR}/${INSTALL_PLUGINSDIR}/${arg_TYPE}") + if ("x${arg_CLASS_NAME}" STREQUAL x) + message(AUTHOR_WARNING "add_qt_plugin called without setting CLASS_NAME.") + endif() + qt_internal_check_directory_or_type(OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" "${arg_TYPE}" "${output_directory_default}" output_directory) qt_internal_check_directory_or_type(INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}" "${arg_TYPE}" @@ -1329,7 +1368,8 @@ function(add_qt_plugin target) set_target_properties("${target}" PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_directory}" RUNTIME_OUTPUT_DIRECTORY "${output_directory}" - ARCHIVE_OUTPUT_DIRECTORY "${output_directory}") + ARCHIVE_OUTPUT_DIRECTORY "${output_directory}" + QT_PLUGIN_CLASS_NAME "${arg_CLASS_NAME}") qt_internal_library_deprecation_level(deprecation_define) @@ -1340,6 +1380,15 @@ function(add_qt_plugin target) set(static_plugin_define "QT_STATICPLUGIN") endif() + # Save the Qt module in the plug-in's properties + qt_get_module_for_plugin("${target}" "${arg_TYPE}") + get_target_property(qt_module "${target}" QT_MODULE) + + # Add the plug-in to the list of plug-ins of this module + if(TARGET "${qt_module}") + set_property(TARGET "${qt_module}" APPEND PROPERTY QT_PLUGINS "${target}") + endif() + extend_target("${target}" SOURCES ${arg_SOURCES} INCLUDE_DIRECTORIES @@ -1379,14 +1428,55 @@ function(add_qt_plugin target) DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS} ) + set(qt_libs_private "") + foreach(it ${QT_KNOWN_MODULES}) + list(FIND arg_LIBRARIES "Qt::${it}Private" pos) + if(pos GREATER -1) + list(APPEND qt_libs_private "Qt::${it}Private") + endif() + endforeach() + + qt_register_target_dependencies("${target}" "${arg_PUBLIC_LIBRARIES}" "${qt_libs_private}") + + # Handle creation of cmake files for consumers of find_package(). + # If we are part of a Qt module, the plugin cmake files are installed as part of that module. + if(qt_module) + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${qt_module}") + else() + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") + endif() + + qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) + qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) + + configure_package_config_file( + "${QT_CMAKE_DIR}/QtPluginConfig.cmake.in" + "${config_build_dir}/${target}Config.cmake" + INSTALL_DESTINATION "${config_install_dir}" + ) + write_basic_package_version_file( + "${config_build_dir}/${target}ConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion + ) + + qt_install(FILES + "${config_build_dir}/${target}Config.cmake" + "${config_build_dir}/${target}ConfigVersion.cmake" + DESTINATION "${config_install_dir}" + COMPONENT Devel + ) + set(export_name "${target}Targets") qt_install(TARGETS "${target}" EXPORT ${export_name} LIBRARY DESTINATION "${install_directory}" - ARCHIVE DESTINATION "${archive_install_directory}") + ARCHIVE DESTINATION "${archive_install_directory}" + ) qt_install(EXPORT ${export_name} NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}:: - DESTINATION ${QT_CONFIG_INSTALL_DIR}) + DESTINATION "${config_install_dir}" + ) ### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins # that belong to Qt. diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake index d11a711788..c7e4764751 100644 --- a/cmake/QtFeature.cmake +++ b/cmake/QtFeature.cmake @@ -506,8 +506,8 @@ function(qt_config_compile_test_x86simd extension label) endfunction() function(qt_make_features_available target) - if(NOT "${target}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::[a-zA-z][a-zA-Z0-9_]*$") - message(FATAL_ERROR "${target} does not match ${QT_CMAKE_EXPORT_NAMESPACE}::[a-zA-z][a-zA-Z0-9_]*. INVALID NAME.") + if(NOT "${target}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::[a-zA-z][a-zA-Z0-9_-]*$") + message(FATAL_ERROR "${target} does not match ${QT_CMAKE_EXPORT_NAMESPACE}::[a-zA-z][a-zA-Z0-9_-]*. INVALID NAME.") endif() if(NOT TARGET ${target}) message(FATAL_ERROR "${target} not found.") @@ -537,3 +537,4 @@ function(qt_make_features_available target) endforeach() endfunction() + diff --git a/cmake/QtModuleConfig.cmake.in b/cmake/QtModuleConfig.cmake.in index 6a68fdf3b0..7c6c6545de 100644 --- a/cmake/QtModuleConfig.cmake.in +++ b/cmake/QtModuleConfig.cmake.in @@ -17,7 +17,6 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake") - foreach(extra_cmake_include @extra_cmake_includes@) include("${CMAKE_CURRENT_LIST_DIR}/${extra_cmake_include}") endforeach() @@ -25,3 +24,8 @@ endforeach() include(${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@/QtFeature.cmake) qt_make_features_available(@QT_CMAKE_EXPORT_NAMESPACE@::@target@) + +set("@INSTALL_CMAKE_NAMESPACE@@target@_FOUND" TRUE) +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Plugins.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Plugins.cmake") +endif() diff --git a/cmake/QtModuleDependencies.cmake.in b/cmake/QtModuleDependencies.cmake.in index 714d2b91ec..f94ba22d9e 100644 --- a/cmake/QtModuleDependencies.cmake.in +++ b/cmake/QtModuleDependencies.cmake.in @@ -3,6 +3,7 @@ set(old_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@") list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@/3rdparty/extra-cmake-modules/find-modules") +list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@/3rdparty/kwin") # note: _third_party_deps example: "ICU\\;1.0\\;i18n uc data;ZLIB\\;\\;" set(_third_party_deps "@third_party_deps@") diff --git a/cmake/QtPluginConfig.cmake.in b/cmake/QtPluginConfig.cmake.in new file mode 100644 index 0000000000..b212d08764 --- /dev/null +++ b/cmake/QtPluginConfig.cmake.in @@ -0,0 +1,13 @@ +@PACKAGE_INIT@ + +include(CMakeFindDependencyMacro) + +get_filename_component(_import_prefix "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_import_prefix "${_import_prefix}" REALPATH) + +# Find required dependencies, if any. +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@target@Dependencies.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/@target@Dependencies.cmake") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@target@Targets.cmake") diff --git a/cmake/QtPluginDependencies.cmake.in b/cmake/QtPluginDependencies.cmake.in new file mode 100644 index 0000000000..0b0db32ca1 --- /dev/null +++ b/cmake/QtPluginDependencies.cmake.in @@ -0,0 +1,53 @@ +# Save old module path, and append a new path that points to the copied over Find modules +# so that find_dependency() can find the third party packages. +set(old_CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}") +list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@") +list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@/3rdparty/extra-cmake-modules/find-modules") +list(APPEND CMAKE_MODULE_PATH "${_import_prefix}/../@INSTALL_CMAKE_NAMESPACE@/3rdparty/kwin") + +# note: _third_party_deps example: "ICU\\;1.0\\;i18n uc data;ZLIB\\;\\;" +set(_third_party_deps "@third_party_deps@") + +foreach(_target_dep ${_third_party_deps}) + list(GET _target_dep 0 pkg) + list(GET _target_dep 1 version) + list(GET _target_dep 2 components) + set(find_package_args "${pkg}") + if(version) + list(APPEND find_package_args "${version}") + endif() + + if(components) + list(APPEND find_package_args "COMPONENTS" ${components}) + endif() + + if (NOT ${pkg}_FOUND) + find_dependency(${find_package_args}) + endif() + + if (NOT ${pkg}_FOUND) + set(@target@_FOUND FALSE) + return() + endif() +endforeach() + +# Restore old module path. +set(CMAKE_MODULE_PATH "${old_CMAKE_MODULE_PATH}") + +# note: target_deps example: "Qt5Core\;5.12.0;Qt5Gui\;5.12.0" +set(_target_deps "@target_deps@") +foreach(_target_dep ${_target_deps}) + list(GET _target_dep 0 pkg) + list(GET _target_dep 1 version) + + if (NOT ${pkg}_FOUND) + find_dependency(${pkg} ${version} + PATHS "${CMAKE_CURRENT_LIST_DIR}/.." NO_DEFAULT_PATH + ) + endif() + + if (NOT ${pkg}_FOUND) + set(@target@_FOUND FALSE) + return() + endif() +endforeach() diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake index 3261284218..d619aebdad 100644 --- a/cmake/QtPostProcess.cmake +++ b/cmake/QtPostProcess.cmake @@ -12,157 +12,248 @@ function(qt_internal_write_depends_file target) file(GENERATE OUTPUT "${outfile}" CONTENT "${contents}") endfunction() -function(qt_internal_create_depends_files) - message("Generating depends files for ${QT_KNOWN_MODULES}...") - foreach (target ${QT_KNOWN_MODULES}) - get_target_property(depends "${target}" LINK_LIBRARIES) - get_target_property(public_depends "${target}" INTERFACE_LINK_LIBRARIES) - get_target_property(target_deps "${target}" _qt_target_deps) - set(target_deps_seen "") - - set(qtdeps "") - set(third_party_deps "") - set(third_party_deps_seen "") - set(tool_deps "") - set(tool_deps_seen "") - set(main_module_tool_deps "") - - foreach (dep ${depends}) - # Normalize module by stripping leading "Qt::" and trailing "Private" - if (dep MATCHES "Qt::(.*)") - set(dep "${CMAKE_MATCH_1}") - endif() - if (dep MATCHES "(.*)Private") - set(dep "${CMAKE_MATCH_1}") - endif() +macro(qt_collect_third_party_deps) + # If we are doing a non-static Qt build, we only want to propagate public dependencies. + # If we are doing a static Qt build, we need to propagate all dependencies. + set(depends_var "public_depends") + if(NOT QT_BUILD_SHARED_LIBS) + set(depends_var "depends") + endif() + + foreach(dep ${${depends_var}}) + # Gather third party packages that should be found when using the Qt module. + # Also handle nolink target dependencies. + string(REGEX REPLACE "_nolink$" "" base_dep "${dep}") + if(NOT base_dep STREQUAL dep) + # Resets target name like Vulkan_nolink to Vulkan, because we need to call + # find_package(Vulkan). + set(dep ${base_dep}) + endif() - list(FIND QT_KNOWN_MODULES "${dep}" _pos) - if (_pos GREATER -1) - list(APPEND qtdeps "${dep}") + if(TARGET ${dep}) + list(FIND third_party_deps_seen ${dep} dep_seen) - # Make the ModuleTool package depend on dep's ModuleTool package. - list(FIND tool_deps_seen ${dep} dep_seen) - if(dep_seen EQUAL -1 AND ${dep} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS) - list(APPEND tool_deps_seen ${dep}) - list(APPEND tool_deps - "${INSTALL_CMAKE_NAMESPACE}${dep}Tools\;${PROJECT_VERSION}") + get_target_property(package_name ${dep} INTERFACE_QT_PACKAGE_NAME) + if(dep_seen EQUAL -1 AND package_name) + list(APPEND third_party_deps_seen ${dep}) + get_target_property(package_version ${dep} INTERFACE_QT_PACKAGE_VERSION) + if(NOT package_version) + set(package_version "") endif() + + get_target_property(package_components ${dep} INTERFACE_QT_PACKAGE_COMPONENTS) + if(NOT package_components) + set(package_components "") + endif() + + list(APPEND third_party_deps + "${package_name}\;${package_version}\;${package_components}") endif() - endforeach() + endif() + endforeach() +endmacro() + +function(qt_internal_create_module_depends_file target) + get_target_property(depends "${target}" LINK_LIBRARIES) + get_target_property(public_depends "${target}" INTERFACE_LINK_LIBRARIES) + get_target_property(target_deps "${target}" _qt_target_deps) + set(target_deps_seen "") - # If we are doing a non-static Qt build, we only want to propagate public dependencies. - # If we are doing a static Qt build, we need to propagate all dependencies. - set(depends_var "public_depends") - if(NOT QT_BUILD_SHARED_LIBS) - set(depends_var "depends") + set(qtdeps "") + set(third_party_deps "") + set(third_party_deps_seen "") + set(tool_deps "") + set(tool_deps_seen "") + set(main_module_tool_deps "") + + foreach (dep ${depends}) + # Normalize module by stripping leading "Qt::" and trailing "Private" + if (dep MATCHES "Qt::(.*)") + set(dep "${CMAKE_MATCH_1}") + endif() + if (dep MATCHES "(.*)Private") + set(dep "${CMAKE_MATCH_1}") endif() - foreach(dep ${${depends_var}}) - # Gather third party packages that should be found when using the Qt module. - # Also handle nolink target dependencies. - string(REGEX REPLACE "_nolink$" "" base_dep "${dep}") - if(NOT base_dep STREQUAL dep) - # Resets target name like Vulkan_nolink to Vulkan, because we need to call - # find_package(Vulkan). - set(dep ${base_dep}) - endif() + list(FIND QT_KNOWN_MODULES "${dep}" _pos) + if (_pos GREATER -1) + list(APPEND qtdeps "${dep}") - if(TARGET ${dep}) - list(FIND third_party_deps_seen ${dep} dep_seen) + # Make the ModuleTool package depend on dep's ModuleTool package. + list(FIND tool_deps_seen ${dep} dep_seen) + if(dep_seen EQUAL -1 AND ${dep} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS) + list(APPEND tool_deps_seen ${dep}) + list(APPEND tool_deps + "${INSTALL_CMAKE_NAMESPACE}${dep}Tools\;${PROJECT_VERSION}") + endif() + endif() + endforeach() - get_target_property(package_name ${dep} INTERFACE_QT_PACKAGE_NAME) - if(dep_seen EQUAL -1 AND package_name) - list(APPEND third_party_deps_seen ${dep}) - get_target_property(package_version ${dep} INTERFACE_QT_PACKAGE_VERSION) - if(NOT package_version) - set(package_version "") - endif() + qt_collect_third_party_deps() - get_target_property(package_components ${dep} INTERFACE_QT_PACKAGE_COMPONENTS) - if(NOT package_components) - set(package_components "") - endif() + # Add dependency to the main ModuleTool package to ModuleDependencies file. + if(${target} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS) + set(main_module_tool_deps + "${INSTALL_CMAKE_NAMESPACE}${target}Tools\;${PROJECT_VERSION}") + endif() - list(APPEND third_party_deps - "${package_name}\;${package_version}\;${package_components}") + # Dirty hack because https://gitlab.kitware.com/cmake/cmake/issues/19200 + foreach(dep ${target_deps}) + if(dep) + list(FIND target_deps_seen "${dep}" dep_seen) + if(dep_seen EQUAL -1) + list(LENGTH dep len) + if(NOT (len EQUAL 2)) + message(FATAL_ERROR "List '${dep}' should look like QtFoo;version") endif() - endif() - endforeach() + list(GET dep 0 dep_name) + list(GET dep 1 dep_ver) - # Add dependency to the main ModuleTool package to ModuleDependencies file. - if(${target} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS) - set(main_module_tool_deps - "${INSTALL_CMAKE_NAMESPACE}${target}Tools\;${PROJECT_VERSION}") + list(APPEND target_deps_seen "${dep_name}\;${dep_ver}") + endif() endif() + endforeach() + set(target_deps "${target_deps_seen}") + + if (DEFINED qtdeps) + list(REMOVE_DUPLICATES qtdeps) + endif() + + get_target_property(hasModuleHeaders "${target}" MODULE_HAS_HEADERS) + if (${hasModuleHeaders}) + qt_internal_write_depends_file("${target}" ${qtdeps}) + endif() + + if(third_party_deps OR main_module_tool_deps OR target_deps) + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") + qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) + qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) + + # Configure and install ModuleDependencies file. + configure_file( + "${QT_CMAKE_DIR}/QtModuleDependencies.cmake.in" + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake" + @ONLY + ) + + qt_install(FILES + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake" + DESTINATION "${config_install_dir}" + COMPONENT Devel + ) - # Dirty hack because https://gitlab.kitware.com/cmake/cmake/issues/19200 - foreach(dep ${target_deps}) - if(dep) - list(FIND target_deps_seen "${dep}" dep_seen) - if(dep_seen EQUAL -1) - list(LENGTH dep len) - if(NOT (len EQUAL 2)) - message(FATAL_ERROR "List '${dep}' should look like QtFoo;version") - endif() - list(GET dep 0 dep_name) - list(GET dep 1 dep_ver) - - list(APPEND target_deps_seen "${dep_name}\;${dep_ver}") + endif() + if(tool_deps) + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}Tools") + qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) + qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) + + # Configure and install ModuleToolDependencies file. + configure_file( + "${QT_CMAKE_DIR}/QtModuleToolsDependencies.cmake.in" + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake" + @ONLY + ) + + qt_install(FILES + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake" + DESTINATION "${config_install_dir}" + COMPONENT Devel + ) + + endif() +endfunction() + +function(qt_internal_create_plugin_depends_file target) + get_target_property(qt_module "${target}" QT_MODULE) + get_target_property(target_deps "${target}" _qt_target_deps) + set(target_deps_seen "") + + qt_collect_third_party_deps() + + # Dirty hack because https://gitlab.kitware.com/cmake/cmake/issues/19200 + foreach(dep ${target_deps}) + if(dep) + list(FIND target_deps_seen "${dep}" dep_seen) + if(dep_seen EQUAL -1) + list(LENGTH dep len) + if(NOT (len EQUAL 2)) + message(FATAL_ERROR "List '${dep}' should look like QtFoo;version") endif() - endif() - endforeach() - set(target_deps "${target_deps_seen}") + list(GET dep 0 dep_name) + list(GET dep 1 dep_ver) - if (DEFINED qtdeps) - list(REMOVE_DUPLICATES qtdeps) + list(APPEND target_deps_seen "${dep_name}\;${dep_ver}") + endif() endif() + endforeach() + set(target_deps "${target_deps_seen}") - get_target_property(hasModuleHeaders "${target}" MODULE_HAS_HEADERS) - if (${hasModuleHeaders}) - qt_internal_write_depends_file("${target}" ${qtdeps}) + if(third_party_deps OR target_deps) + # Setup build and install paths + if(qt_module) + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${qt_module}") + else() + set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") endif() - if(third_party_deps OR main_module_tool_deps OR target_deps) - set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}") - qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) - qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) - - # Configure and install ModuleDependencies file. - configure_file( - "${QT_CMAKE_DIR}/QtModuleDependencies.cmake.in" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake" - @ONLY - ) - - qt_install(FILES - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Dependencies.cmake" - DESTINATION "${config_install_dir}" - COMPONENT Devel - ) + qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) + qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) - endif() - if(tool_deps) - set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}Tools") - qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix}) - qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix}) - - # Configure and install ModuleToolDependencies file. - configure_file( - "${QT_CMAKE_DIR}/QtModuleToolsDependencies.cmake.in" - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake" - @ONLY - ) - - qt_install(FILES - "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ToolsDependencies.cmake" - DESTINATION "${config_install_dir}" - COMPONENT Devel - ) + # Configure and install ModuleDependencies file. + configure_file( + "${QT_CMAKE_DIR}/QtPluginDependencies.cmake.in" + "${config_build_dir}/${target}Dependencies.cmake" + @ONLY + ) - endif() + qt_install(FILES + "${config_build_dir}/${target}Dependencies.cmake" + DESTINATION "${config_install_dir}" + COMPONENT Devel + ) + endif() +endfunction() + +# Create Depends.cmake & Depends.h files for all modules and plug-ins. +function(qt_internal_create_depends_files) + message("Generating depends files for ${QT_KNOWN_MODULES}...") + foreach (target ${QT_KNOWN_MODULES}) + qt_internal_create_module_depends_file(${target}) endforeach() + message("Generating depends files for ${QT_KNOWN_PLUGINS}...") + foreach (target ${QT_KNOWN_PLUGINS}) + qt_internal_create_plugin_depends_file(${target}) + endforeach() +endfunction() +# This function creates the QtPlugins.cmake used to list all +# the plug-in target files. +function(qt_internal_create_plugins_files) + message("Generating Plugins files for ${QT_KNOWN_MODULES}...") + foreach (target ${QT_KNOWN_MODULES}) + qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${INSTALL_CMAKE_NAMESPACE}${target}) + qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${INSTALL_CMAKE_NAMESPACE}${target}) + + set(_plugins_file "") + get_target_property(qt_plugins "${target}" QT_PLUGINS) + if(qt_plugins) + foreach (plugin ${qt_plugins}) + set(_plugins_file "${_plugins_file}include(\"\${CMAKE_CURRENT_LIST_DIR}/${plugin}Config.cmake\")\n") + endforeach() + + if(NOT ("x${_plugins_file}" STREQUAL "x")) + file(WRITE "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Plugins.cmake" "${_plugins_file}") + + qt_install(FILES + "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Plugins.cmake" + DESTINATION "${config_install_dir}" + COMPONENT Devel + ) + endif() + endif() + endforeach() endfunction() function(qt_generate_build_internals_extra_cmake_code) @@ -203,3 +294,4 @@ endfunction() qt_internal_create_depends_files() qt_generate_build_internals_extra_cmake_code() +qt_internal_create_plugins_files() diff --git a/cmake/QtProperties.cmake b/cmake/QtProperties.cmake new file mode 100644 index 0000000000..f2bb2c5c59 --- /dev/null +++ b/cmake/QtProperties.cmake @@ -0,0 +1,8 @@ +define_property(TARGET + PROPERTY + QT_PLUGIN_CLASS_NAME + BRIEF_DOCS + "Class name of the Qt plug-in" + FULL_DOCS + "For instance, QICOPlugin for the qico plug-in" +) -- cgit v1.2.3