diff --git a/cmake/Qt3rdPartyLibraryHelpers.cmake b/cmake/Qt3rdPartyLibraryHelpers.cmake index 27d615b2b4..7cfa943567 100644 --- a/cmake/Qt3rdPartyLibraryHelpers.cmake +++ b/cmake/Qt3rdPartyLibraryHelpers.cmake @@ -49,11 +49,6 @@ function(qt_internal_add_cmake_library target) endif() qt_skip_warnings_are_errors_when_repo_unclean("${target}") - # No need to compile Q_IMPORT_PLUGIN-containing files for non-executables. - if(is_static_lib) - _qt_internal_disable_static_default_plugins("${target}") - endif() - if (arg_INSTALL_DIRECTORY) set(install_arguments ARCHIVE_INSTALL_DIRECTORY ${arg_ARCHIVE_INSTALL_DIRECTORY} @@ -145,11 +140,6 @@ function(qt_internal_add_3rdparty_library target) qt_internal_add_target_aliases(${target}) _qt_internal_apply_strict_cpp(${target}) - # No need to compile Q_IMPORT_PLUGIN-containing files for non-executables. - if(is_static_lib) - _qt_internal_disable_static_default_plugins("${target}") - endif() - if (ANDROID) qt_android_apply_arch_suffix("${target}") endif() diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 4cb212c169..4d976173df 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -144,11 +144,6 @@ function(qt_internal_add_module target) qt_skip_warnings_are_errors_when_repo_unclean("${target}") _qt_internal_apply_strict_cpp("${target}") - # No need to compile Q_IMPORT_PLUGIN-containing files for non-executables. - if(is_static_lib) - _qt_internal_disable_static_default_plugins("${target}") - endif() - # Add _private target to link against the private headers: if(NOT ${arg_NO_PRIVATE_MODULE}) set(target_private "${target}Private") diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index 2368531d99..c4e0df4415 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -119,10 +119,6 @@ function(qt_internal_add_plugin target) qt_skip_warnings_are_errors_when_repo_unclean("${target}") _qt_internal_apply_strict_cpp("${target}") - # Disable linking of plugins against other plugins during static regular and - # super builds. The latter causes cyclic dependencies otherwise. - _qt_internal_disable_static_default_plugins("${target}") - set_target_properties("${target}" PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_directory}" RUNTIME_OUTPUT_DIRECTORY "${output_directory}" @@ -322,8 +318,13 @@ function(qt_internal_add_plugin target) endforeach() qt_register_target_dependencies("${target}" "${arg_PUBLIC_LIBRARIES}" "${qt_libs_private}") + set(plugin_init_target "") if (NOT BUILD_SHARED_LIBS) qt_generate_plugin_pri_file("${target}" pri_file) + + if(qt_module_target) + __qt_internal_add_static_plugin_init_object_library("${target}" plugin_init_target) + endif() endif() if (NOT arg_SKIP_INSTALL) @@ -372,10 +373,13 @@ function(qt_internal_add_plugin target) # Make the export name of plugins be consistent with modules, so that # qt_add_resource adds its additional targets to the same export set in a static Qt build. set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets") - qt_install(TARGETS "${target}" + qt_install(TARGETS + "${target}" + ${plugin_init_target} EXPORT ${export_name} RUNTIME DESTINATION "${install_directory}" LIBRARY DESTINATION "${install_directory}" + OBJECTS DESTINATION "${install_directory}" ARCHIVE DESTINATION "${archive_install_directory}" ) qt_install(EXPORT ${export_name} diff --git a/cmake/QtPublicPluginHelpers.cmake b/cmake/QtPublicPluginHelpers.cmake index 39143cecc3..34790fe6a3 100644 --- a/cmake/QtPublicPluginHelpers.cmake +++ b/cmake/QtPublicPluginHelpers.cmake @@ -1,3 +1,5 @@ +# Gets the qt plugin type of the given plugin into out_var_plugin_type. +# Also sets out_var_has_plugin_type to TRUE or FALSE depending on whether the plugin type was found. function(__qt_internal_plugin_get_plugin_type plugin_target out_var_has_plugin_type @@ -17,8 +19,8 @@ function(__qt_internal_plugin_get_plugin_type set(${out_var_has_plugin_type} "${has_plugin_type}" PARENT_SCOPE) endfunction() +# Gets the qt plugin class name of the given target into out_var. function(__qt_internal_plugin_has_class_name plugin_target out_var) - set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}") get_target_property(classname "${plugin_target_versioned}" QT_PLUGIN_CLASS_NAME) @@ -118,6 +120,7 @@ function(__qt_internal_get_static_plugin_condition_genex set(${out_var} "${_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) @@ -128,36 +131,77 @@ function(__qt_internal_add_static_plugin_linkage plugin_target qt_module_target) target_link_libraries(${qt_module_target} INTERFACE "${plugin_genex}") endfunction() +# Generates C++ import macro source code for given plugin +function(__qt_internal_get_plugin_import_macro plugin_target out_var) + set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}") + get_target_property(class_name "${plugin_target_versioned}" QT_PLUGIN_CLASS_NAME) + set(${out_var} "Q_IMPORT_PLUGIN(${class_name})" PARENT_SCOPE) +endfunction() + +function(__qt_internal_get_plugin_include_prelude out_var) + set(${out_var} "#include \n" PARENT_SCOPE) +endfunction() + +# Set up plugin initialization via usage requirements of associated Qt module. +# +# Adds the plugin init object library as an INTERFACE source of the plugin target. +# This is similar to how it was done before, except instead of generating a C++ file and compiling +# it as part of the user project, we just specify the pre-compiled object file as an INTERFACE +# source so that user projects don't have to compile it. User project builds will thus be shorter. function(__qt_internal_add_static_plugin_import_macro plugin_target qt_module_target qt_module_unprefixed) - set(_generated_qt_plugin_file_name - "${CMAKE_CURRENT_BINARY_DIR}/.qt_plugins/qt_${qt_module_unprefixed}_${plugin_target}.cpp") - set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}") - get_target_property(class_name "${plugin_target_versioned}" QT_PLUGIN_CLASS_NAME) + __qt_internal_get_static_plugin_init_target_name("${plugin_target}" plugin_init_target) + set(objs_genex "$") - set(_generated_qt_plugin_file_content "#include \nQ_IMPORT_PLUGIN(${class_name})") - - # Generate a source file to import that plug-in. Be careful not to - # update the timestamp of the generated file if we are not going to - # change anything. Otherwise we will trigger CMake's autogen to re-run - # and executables will then need to at least relink. - set(need_write TRUE) - if(EXISTS ${_generated_qt_plugin_file_name}) - file(READ ${_generated_qt_plugin_file_name} old_contents) - if(old_contents STREQUAL "${_generated_qt_plugin_file_content}") - set(need_write FALSE) - endif() - endif() - if(need_write) - file(WRITE "${_generated_qt_plugin_file_name}" - "${_generated_qt_plugin_file_content}") - endif() - - __qt_internal_get_static_plugin_condition_genex("${plugin_target}" plugin_condition) - - target_sources(${qt_module_target} INTERFACE - "$<${plugin_condition}:${_generated_qt_plugin_file_name}>") + target_sources(${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target} INTERFACE + "${objs_genex}") endfunction() + +# Get target name of object library which is used to initialize a qt plugin. +function(__qt_internal_get_static_plugin_init_target_name plugin_target out_var) + # Keep the target name short, so we don't hit long path issues on Windows. + set(plugin_init_target "${plugin_target}_init") + + set(${out_var} "${plugin_init_target}" PARENT_SCOPE) +endfunction() + +# Create an object library that initializes a static qt plugin. +# +# The object library contains a single generated C++ file that calls Q_IMPORT_PLUGIN(plugin_class). +# The object library is exported as part of the Qt build and consumed by user applications +# that link to qt plugins. +# +# The created target name is assigned to 'out_var_plugin_init_target'. +function(__qt_internal_add_static_plugin_init_object_library + plugin_target + out_var_plugin_init_target) + + __qt_internal_get_plugin_import_macro(${plugin_target} import_macro) + __qt_internal_get_plugin_include_prelude(include_prelude) + set(import_content "${include_prelude}${import_macro}") + + string(MAKE_C_IDENTIFIER "${plugin_target}" plugin_target_identifier) + set(generated_qt_plugin_file_name + "${CMAKE_CURRENT_BINARY_DIR}/${plugin_target_identifier}_init.cpp") + + file(GENERATE + OUTPUT "${generated_qt_plugin_file_name}" + CONTENT "${import_content}" + ) + + __qt_internal_get_static_plugin_init_target_name("${plugin_target}" plugin_init_target) + + add_library("${plugin_init_target}" OBJECT "${generated_qt_plugin_file_name}") + target_link_libraries(${plugin_init_target} + PRIVATE + + # Core provides the symbols needed by Q_IMPORT_PLUGIN. + ${QT_CMAKE_EXPORT_NAMESPACE}::Core + ) + + set(${out_var_plugin_init_target} "${plugin_init_target}" PARENT_SCOPE) +endfunction() + diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 6e825c2a63..01426cd8ea 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -1373,9 +1373,6 @@ function(__qt_propagate_generated_resource target resource_name generated_source target_link_libraries(${target} INTERFACE ${resource_target}) endif() set(${output_generated_target} "${resource_target}" PARENT_SCOPE) - - # No need to compile Q_IMPORT_PLUGIN-containing files for non-executables. - _qt_internal_disable_static_default_plugins("${resource_target}") else() set(${output_generated_target} "" PARENT_SCOPE) target_sources(${target} PRIVATE ${generated_source_code})