Allow linking all plugin initializer object libraries directly
into the final target (executable or shared library).
The finalizer mode is triggered when the project adds a call
to qt_import_plugins, as well when the project has an explicit
call to qt_finalize_executable or when it is defer called by
CMake 3.19+.
Otherwise the old non-finalizer mode is used, where each plugin
initializer object library is propagated via the usage
requirements of its associated module.
A user can explicitly opt in or out of the new mode by calling
qt_enable_import_plugins_finalizer_mode(target TRUE/FALSE)
The implementation, at configure time, recursively collects all
dependencies of the target to extract a list of used Qt modules.
From each module we extract its list of associated plugins and
their genex conditions. These genexes are used to conditionally
link the plugins and the initializers.
Renamed QT_PLUGINS property to _qt_plugins, so we can safely query the
property even on INTERFACE libraries with lower CMake versions.
QT_PLUGINS is kept for backwards compatibility with projects already
using it, but should be removed in Qt 7.
The upside of the finalizer mode is that it avoids creating link
cycles (e.g. Gui -> SvgPlugin -> Gui case) which causes CMake to
duplicate the library on the link line, slowing down link time as well
as possibly breaking link order dependencies.
The downside is that finalizer mode can't cope with generator
expressions at the moment. So if a Qt module target is wrapped in a
generator expression, it's plugins will not be detected and thus
linked.
Task-number: QTBUG-80863
Task-number: QTBUG-92933
Change-Id: Ic40c8ae5807a154ed18fcac18b25f00864c8f143
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Instead of compiling the plugin initializers as part of a user
project, pre-compile them as object libraries while building Qt.
The installed object libraries can then be used with
target_sources(qt_module INTERFACE $<TARGET_OBJECTS:plugin_init>)
so that they are linked into the final executable or shared library
via qt module usage requirement propagation.
This reduces the build times of user projects.
The link line placement of the object files should be correct for all
linux-y linkers because the only dependency for the object files is
Core and the Gui -> plugin -> Gui -> Core cycle does not hamper that
from empirical observations.
As a consequence of the recent change not to link plugin initialization
object files into static libraries, as well not having to compile the
files in user projects, we can get rid of the
_qt_internal_disable_static_default_plugins calls in various places.
A side note.
Consider a user static library (L) that links to a Qt static library
(Gui) which provides plugins (platform plugins).
If there is an executable (E) that links to (L), with no direct
dependency to any other Qt module and the intention is that the
executable will automatically get the platform plugin linked,
then (L) needs to link PUBLIC-ly to (Gui) so that the plugin usage
requirements are propagated successfully.
This is a limitation of using
target_sources(qt_module INTERFACE $<TARGET_OBJECTS:plugin_init>)
which will propagate object files across static libraries only if
qt_module is linked publicly.
One could try to use
target_link_libraries(qt_module
INTERFACE $<TARGET_OBJECTS:plugin_init>)
which preserves the linker arguments across static libs even if
qt_module is linked privately, but unfortunately CMake will lose
dependency information on Core, which means the object files might be
placed in the wrong place on the link line.
As far as I know this is a limitation of CMake that can't be worked
around at the moment.
Note this behavior was present before this change as well.
Task-number: QTBUG-80863
Task-number: QTBUG-92933
Change-Id: Ia99e8aa3d32d6197cacd6162515ac808f2c6c53f
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Q_IMPORT_PLUGIN generates a global static symbol that initializes a
plugin. If this symbol is added to a static library and the library
is then linked to an executable, the linker decides that the symbol is
unused (because nothing references it) and discards it.
This means there's no point to compile the Q_IMPORT_PLUGIN containing
files into static libraries.
Change the generator expression we use for plugin propagation via
associated modules to not compile and link the plugin initialization
object file into a static library.
Pick-to: 6.1
Task-number: QTBUG-80863
Change-Id: Ide32c0124c1e313c352a72280ce32ce9fbe8fff1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Extract common static plugin handling functionality into a separate
QtPublicPluginHelpers.cmake file which is loaded by the Qt6 package.
Split the code into smaller functions that will be re-used by each
templated QtPlugins.cmake.in file, rather than copy pasting the same
code into each QtFooPlugins.cmake file.
As a drive-by, handle QtFeatures.cmake and QtFeaturesCommon.cmake
as public helper files just like QtPublicPluginHelpers.cmake.
This makes it clearer that the functions are available outside
the internal Qt build and also provides a way for not dumping new
helper functions into Qt6CoreMacros.cmake.
Task-number: QTBUG-92933
Change-Id: Id816ef009b4fac1cd317d3ef23f21b3530028067
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>