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: [PATCH] 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 | 362 ++++++++++++-------- cmake/QtProperties.cmake | 8 + src/gui/CMakeLists.txt | 10 + src/plugins/imageformats/ico/CMakeLists.txt | 2 + src/sql/CMakeLists.txt | 2 + util/cmake/pro2cmake.py | 21 +- 12 files changed, 463 insertions(+), 178 deletions(-) create mode 100644 cmake/QtPluginConfig.cmake.in create mode 100644 cmake/QtPluginDependencies.cmake.in create mode 100644 cmake/QtProperties.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 "") +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() - 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_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() - 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() + if(TARGET ${dep}) + list(FIND third_party_deps_seen ${dep} dep_seen) - list(FIND QT_KNOWN_MODULES "${dep}" _pos) - if (_pos GREATER -1) - list(APPEND qtdeps "${dep}") - - # 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() - endif() - endforeach() - # 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() - - if(TARGET ${dep}) - list(FIND third_party_deps_seen ${dep} dep_seen) - - 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}") + 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() - # 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}") +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 "") + + 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() - # 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(FIND QT_KNOWN_MODULES "${dep}" _pos) + if (_pos GREATER -1) + list(APPEND qtdeps "${dep}") - list(APPEND target_deps_seen "${dep_name}\;${dep_ver}") - endif() + # 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() - 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 - ) - - 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() endforeach() + qt_collect_third_party_deps() + # 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() + + # 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() + 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 + ) + + 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() + list(GET dep 0 dep_name) + list(GET dep 1 dep_ver) + + list(APPEND target_deps_seen "${dep_name}\;${dep_ver}") + endif() + endif() + endforeach() + set(target_deps "${target_deps_seen}") + + 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() + + 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}/QtPluginDependencies.cmake.in" + "${config_build_dir}/${target}Dependencies.cmake" + @ONLY + ) + + 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" +) diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index b3f5a880b1..50e966d34d 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -39,6 +39,16 @@ endif() # special case end add_qt_module(Gui + PLUGIN_TYPES + platforms + platforms/darwin + xcbglintegrations + platformthemes + platforminputcontexts + generic + iconengines + imageformats + egldeviceintegrations FEATURE_DEPENDENCIES # special case: Qt::Network # special case: SOURCES diff --git a/src/plugins/imageformats/ico/CMakeLists.txt b/src/plugins/imageformats/ico/CMakeLists.txt index 160b440dff..976ab98266 100644 --- a/src/plugins/imageformats/ico/CMakeLists.txt +++ b/src/plugins/imageformats/ico/CMakeLists.txt @@ -13,6 +13,8 @@ add_qt_plugin(qico Qt::GuiPrivate # special case PUBLIC_LIBRARIES # special case Qt::Gui # special case + CLASS_NAME + QICOPlugin ) #### Keys ignored in scope 1:.:.:ico.pro:: diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index f84d12dc12..8f728e7079 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -5,6 +5,8 @@ ##################################################################### add_qt_module(Sql + PLUGIN_TYPES + sqldrivers SOURCES kernel/qsqlcachedresult.cpp kernel/qsqlcachedresult_p.h kernel/qsqldatabase.cpp kernel/qsqldatabase.h diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py index dfe407da6d..3b37991cba 100755 --- a/util/cmake/pro2cmake.py +++ b/util/cmake/pro2cmake.py @@ -1193,11 +1193,6 @@ def write_sources_section(cm_fh: typing.IO[str], scope: Scope, *, # mark RESOURCES as visited: scope.get('RESOURCES') - plugin_type = scope.get_string('PLUGIN_TYPE') - - if plugin_type: - cm_fh.write('{} TYPE {}\n'.format(ind, plugin_type)) - write_all_source_file_lists(cm_fh, scope, 'SOURCES', indent=indent + 1) write_source_file_list(cm_fh, scope, 'DBUS_ADAPTOR_SOURCES', ['DBUS_ADAPTORS',], indent + 1) @@ -1611,6 +1606,10 @@ def write_module(cm_fh: typing.IO[str], scope: Scope, *, if len(module_config): extra.append('QMAKE_MODULE_CONFIG {}'.format(" ".join(module_config))) + module_plugin_types = scope.get_files('MODULE_PLUGIN_TYPES') + if module_plugin_types: + extra.append('PLUGIN_TYPES {}'.format(" ".join(module_plugin_types))) + write_main_part(cm_fh, module_name[2:], 'Module', 'add_qt_module', scope, extra_lines=extra, indent=indent, known_libraries={}, extra_keys=[]) @@ -1726,8 +1725,18 @@ def write_plugin(cm_fh, scope, *, indent: int = 0): plugin_name = scope.TARGET assert plugin_name + extra = [] + + plugin_type = scope.get_string('PLUGIN_TYPE') + if plugin_type: + extra.append('TYPE {}'.format(plugin_type)) + + plugin_class_name = scope.get_string('PLUGIN_CLASS_NAME') + if plugin_class_name: + extra.append('CLASS_NAME {}'.format(plugin_class_name)) + write_main_part(cm_fh, plugin_name, 'Plugin', 'add_qt_plugin', scope, - indent=indent, known_libraries={}, extra_keys=[]) + indent=indent, extra_lines=extra, known_libraries={}, extra_keys=[]) def handle_app_or_lib(scope: Scope, cm_fh: typing.IO[str], *,