summaryrefslogtreecommitdiffstats
path: root/cmake/QtPublicPluginHelpers.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/QtPublicPluginHelpers.cmake')
-rw-r--r--cmake/QtPublicPluginHelpers.cmake182
1 files changed, 180 insertions, 2 deletions
diff --git a/cmake/QtPublicPluginHelpers.cmake b/cmake/QtPublicPluginHelpers.cmake
index 34790fe6a3..35026fa395 100644
--- a/cmake/QtPublicPluginHelpers.cmake
+++ b/cmake/QtPublicPluginHelpers.cmake
@@ -32,6 +32,13 @@ function(__qt_internal_plugin_has_class_name plugin_target out_var)
set(${out_var} "${classname}" PARENT_SCOPE)
endfunction()
+# Constructs a generator expression which decides whether a plugin will be used.
+#
+# The conditions are based on the various properties set in qt_import_plugins.
+
+# All the TARGET_PROPERTY genexes are evaluated in the context of the currently linked target.
+#
+# The genex is saved into out_var.
function(__qt_internal_get_static_plugin_condition_genex
plugin_target_unprefixed
out_var)
@@ -49,9 +56,10 @@ function(__qt_internal_get_static_plugin_condition_genex
# Plugin genex marker for prl processing.
set(_is_plugin_marker_genex "$<BOOL:QT_IS_PLUGIN_GENEX>")
- # The code in here uses the properties defined in qt_import_plugins (Qt6CoreMacros.cmake)
set(_plugin_is_default "$<TARGET_PROPERTY:${plugin_target},QT_DEFAULT_PLUGIN>")
+ # The code in here uses the properties defined in qt_import_plugins (Qt6CoreMacros.cmake)
+
# INCLUDE
set(_plugin_is_whitelisted "$<IN_LIST:${plugin_target},${_manual_plugins_genex}>")
set(_plugin_versionless_is_whitelisted
@@ -120,14 +128,23 @@ function(__qt_internal_get_static_plugin_condition_genex
set(${out_var} "${_plugin_condition}" PARENT_SCOPE)
endfunction()
+# Wraps the genex condition to evaluate to true only when using the regular plugin importing mode
+# (not finalizer mode).
+function(__qt_internal_get_plugin_condition_regular_mode plugin_condition out_var)
+ set(not_finalizer_mode "$<NOT:$<BOOL:$<TARGET_PROPERTY:_qt_static_plugins_use_finalizer_mode>>>")
+ set(full_plugin_condition "$<AND:${plugin_condition},${not_finalizer_mode}>")
+ set(${out_var} "${full_plugin_condition}" PARENT_SCOPE)
+endfunction()
+
# Link plugin via usage requirements of associated Qt module.
function(__qt_internal_add_static_plugin_linkage plugin_target qt_module_target)
__qt_internal_get_static_plugin_condition_genex("${plugin_target}" plugin_condition)
+ __qt_internal_get_plugin_condition_regular_mode("${plugin_condition}" full_plugin_condition)
set(plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
# If this condition is true, we link against the plug-in
- set(plugin_genex "$<${plugin_condition}:${plugin_target}>")
+ set(plugin_genex "$<${full_plugin_condition}:${plugin_target}>")
target_link_libraries(${qt_module_target} INTERFACE "${plugin_genex}")
endfunction()
@@ -205,3 +222,164 @@ function(__qt_internal_add_static_plugin_init_object_library
set(${out_var_plugin_init_target} "${plugin_init_target}" PARENT_SCOPE)
endfunction()
+# Collect a list of genexes to link plugin libraries.
+function(__qt_internal_collect_plugin_libraries plugin_targets out_var)
+ set(plugins_to_link "")
+
+ foreach(plugin_target ${plugin_targets})
+ __qt_internal_get_static_plugin_condition_genex(
+ "${plugin_target}"
+ plugin_condition)
+
+ set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
+
+ list(APPEND plugins_to_link "$<${plugin_condition}:${plugin_target_versioned}>")
+ endforeach()
+
+ set("${out_var}" "${plugins_to_link}" PARENT_SCOPE)
+endfunction()
+
+# Collect a list of genexes to link plugin initializer object libraries.
+#
+# The object libraries are only linked if the associated plugins are linked.
+function(__qt_internal_collect_plugin_init_libraries plugin_targets out_var)
+ set(plugin_inits_to_link "")
+
+ foreach(plugin_target ${plugin_targets})
+ __qt_internal_get_static_plugin_condition_genex(
+ "${plugin_target}"
+ plugin_condition)
+
+ __qt_internal_get_static_plugin_init_target_name("${plugin_target}" plugin_init_target)
+ set(plugin_init_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_init_target}")
+
+ list(APPEND plugin_inits_to_link "$<${plugin_condition}:${plugin_init_target_versioned}>")
+ endforeach()
+
+ set("${out_var}" "${plugin_inits_to_link}" PARENT_SCOPE)
+endfunction()
+
+# Collects all plugin targets discovered by walking the dependencies of ${target}.
+#
+# Walks immediate dependencies and their transitive dependencies.
+# Plugins are collected by inspecting the _qt_plugins property found on any dependency Qt target.
+function(__qt_internal_collect_plugin_targets_from_dependencies target out_var)
+ set(dep_targets "")
+
+ __qt_internal_collect_all_target_dependencies("${target}" dep_targets)
+
+ set(plugin_targets "")
+ foreach(dep_target ${dep_targets})
+ get_target_property(plugins ${dep_target} _qt_plugins)
+ if(plugins)
+ list(APPEND plugin_targets ${plugins})
+ endif()
+ endforeach()
+
+ # Plugins that are specified via qt_import_plugin's INCLUDE or INCLUDE_BY_TYPE can have
+ # dependencies on Qt modules. These modules in turn might bring in more default plugins to link
+ # So it's recursive. Do only one pass for now. Try to extract the included static plugins, walk
+ # their public and private dependencies, check if any of them are Qt modules that provide more
+ # plugins and extract the target names of those plugins.
+ __qt_internal_collect_plugin_targets_from_dependencies_of_plugins(
+ "${target}" recursive_plugin_targets)
+ if(recursive_plugin_targets)
+ list(APPEND plugin_targets ${recursive_plugin_targets})
+ endif()
+ list(REMOVE_DUPLICATES plugin_targets)
+
+ set("${out_var}" "${plugin_targets}" PARENT_SCOPE)
+endfunction()
+
+# Helper to collect plugin targets from encountered module dependencies as a result of walking
+# dependencies. These module dependencies might expose additional plugins.
+function(__qt_internal_collect_plugin_targets_from_dependencies_of_plugins target out_var)
+ set(assigned_plugins_overall "")
+
+ get_target_property(assigned_qt_plugins "${target}" QT_PLUGINS)
+
+ if(assigned_qt_plugins)
+ foreach(assigned_qt_plugin ${assigned_qt_plugins})
+ if(TARGET "${assigned_qt_plugin}")
+ list(APPEND assigned_plugins_overall "${assigned_qt_plugin}")
+ endif()
+ endforeach()
+ endif()
+
+ get_target_property(assigned_qt_plugins_by_type "${target}" _qt_plugins_by_type)
+
+ if(assigned_qt_plugins_by_type)
+ foreach(assigned_qt_plugin ${assigned_qt_plugins_by_type})
+ if(TARGET "${assigned_qt_plugin}")
+ list(APPEND assigned_plugins_overall "${assigned_qt_plugin}")
+ endif()
+ endforeach()
+ endif()
+
+ set(plugin_targets "")
+ foreach(target ${assigned_plugins_overall})
+ __qt_internal_walk_libs(
+ "${target}"
+ dep_targets
+ _discarded_out_var
+ "qt_private_link_library_targets"
+ "collect_targets")
+
+ foreach(dep_target ${dep_targets})
+ get_target_property(plugins ${dep_target} _qt_plugins)
+ if(plugins)
+ list(APPEND plugin_targets ${plugins})
+ endif()
+ endforeach()
+ endforeach()
+
+ list(REMOVE_DUPLICATES plugin_targets)
+
+ set("${out_var}" "${plugin_targets}" PARENT_SCOPE)
+endfunction()
+
+# Helper to check if the finalizer mode of plugin importing should be used.
+# If true or unset, use finalizer mode.
+# If false, use regular mode (usage requirement propagation via associated Qt module)
+function(__qt_internal_get_plugin_imports_finalizer_mode target out_var)
+ get_target_property(value ${target} _qt_static_plugins_use_finalizer_mode)
+ if("${value}" STREQUAL "value-NOTFOUND")
+ set(value "")
+ endif()
+ set(${out_var} "${value}" PARENT_SCOPE)
+endfunction()
+
+# Main logic of finalizer mode.
+function(__qt_internal_apply_plugin_imports_finalizer_mode target)
+ # Nothing to do in a shared build.
+ if(QT6_IS_SHARED_LIBS_BUILD)
+ return()
+ endif()
+
+ # Process a target only once.
+ get_target_property(processed ${target} _qt_plugin_finalizer_imports_processed)
+ if(processed)
+ return()
+ endif()
+
+ __qt_internal_get_plugin_imports_finalizer_mode(${target} use_finalizer_mode)
+
+ # By default if the project hasn't explicitly opted in or out, use finalizer mode.
+ if("${use_finalizer_mode}" STREQUAL "")
+ qt_enable_import_plugins_finalizer_mode(${target} TRUE)
+ endif()
+
+ # Check if the project chose a mode explicitly.
+ __qt_internal_get_plugin_imports_finalizer_mode(${target} use_finalizer_mode)
+ if(NOT use_finalizer_mode)
+ return()
+ endif()
+
+ __qt_internal_collect_plugin_targets_from_dependencies("${target}" plugin_targets)
+ __qt_internal_collect_plugin_init_libraries("${plugin_targets}" init_libraries)
+ __qt_internal_collect_plugin_libraries("${plugin_targets}" plugin_libraries)
+
+ target_link_libraries(${target} PRIVATE "${plugin_libraries}" "${init_libraries}")
+
+ set_target_properties(${target} PROPERTIES _qt_plugin_finalizer_imports_processed TRUE)
+endfunction()