CMake: Revise plugin finalizer mode usage
Only use plugin finalizer mode if qt_finalize_target is called at the
end of the user project (which we can't really check, the user has to
ensure that) or when qt_finalize_target is automatically defer-called
by CMake 3.19+ (which is done by qt_add_executable).
This removes the previous behavior of using the finalizer mode if
qt_import_plugins is called. Instead the old regular mode is used
if the above preconditions are not met.
The removed behavior had ordering issues if qt_import_plugins was called
before target_link_libraries. The dependency walking would be done
before Qt dependencies were added and thus no plugins would be
linked.
Amends 6fcc272ac9
Task-number: QTBUG-80863
Task-number: QTBUG-92933
Task-number: QTBUG-94030
Change-Id: I78702b653a35596f5581c2f4282b2336f0124e60
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
parent
a1c8530a91
commit
a3c430f390
@ -365,6 +365,8 @@ function(__qt_internal_apply_plugin_imports_finalizer_mode target)
|
||||
__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.
|
||||
# The precondition for this is that qt_finalize_target was called (either explicitly by the user
|
||||
# or auto-deferred by CMake 3.19+).
|
||||
if("${use_finalizer_mode}" STREQUAL "")
|
||||
qt_enable_import_plugins_finalizer_mode(${target} TRUE)
|
||||
endif()
|
||||
|
@ -591,8 +591,8 @@ function(_qt_internal_finalize_executable target)
|
||||
# For finalizer mode of plugin importing to work safely, we need to know the list of Qt
|
||||
# dependencies the target has, but those might be added later than the qt_add_executable call.
|
||||
# Most of our examples are like that. Only enable finalizer mode when we are sure that the user
|
||||
# manually finalized the executable, or it was automatically done via a deferred call.
|
||||
# A project can still do it manually by calling qt_import_plugins() explicitly.
|
||||
# manually called qt_finalize_target at the end of their CMake project, or it was automatically
|
||||
# done via a deferred call.
|
||||
get_target_property(is_immediately_finalized "${target}" _qt_is_immediately_finalized)
|
||||
if(NOT is_immediately_finalized)
|
||||
__qt_internal_apply_plugin_imports_finalizer_mode("${target}")
|
||||
@ -868,15 +868,6 @@ function(qt6_import_plugins target)
|
||||
string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}")
|
||||
set_property(TARGET "${target}" PROPERTY "QT_PLUGINS_${_plugin_type}" "-")
|
||||
endforeach()
|
||||
|
||||
# If the project called qt_import_plugins, use this as an event to enable finalizer mode for
|
||||
# plugin importing.
|
||||
#
|
||||
# This is done in addition to the code in qt_finalize_target, to ensure pre-existing
|
||||
# projects that use qt_import_plugins activate finalizer mode even with an older CMake version
|
||||
# that doesn't support deferred calls (and projects that don't explicitly call
|
||||
# qt_finalize_target).
|
||||
__qt_internal_apply_plugin_imports_finalizer_mode(${target})
|
||||
endfunction()
|
||||
|
||||
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
||||
@ -901,8 +892,7 @@ endif()
|
||||
# of its associated module.
|
||||
#
|
||||
# Finalizer mode is enabled by default if:
|
||||
# - the project calls qt_import_plugins explicitly or
|
||||
# - the project calls qt_finalize_target explicitly or
|
||||
# - the project calls qt_finalize_target explicitly at the end of the project file or
|
||||
# - the project uses qt_add_executable and a CMake version greater than or equal to 3.19
|
||||
# (which will DEFER CALL qt_finalize_target)
|
||||
function(qt6_enable_import_plugins_finalizer_mode target enabled)
|
||||
|
@ -72,43 +72,52 @@ create_test_executable(default_link QMock1Plugin QMock2Plugin
|
||||
target_link_libraries(${target} PRIVATE Qt6::MockPlugins2)
|
||||
|
||||
# Check that both regular and finalizer mode plugin importing pulls in the same set of plugins.
|
||||
# In regular mode, qt_finalize_target won't execute the finalizer plugin importing, because
|
||||
# we opt out via qt_enable_import_plugins_finalizer_mode(target FALSE).
|
||||
foreach(import_mode "" "FINALIZER_MODE")
|
||||
create_test_executable(manual QMock1Plugin QMock2Plugin QMock3Plugin QMock4Plugin
|
||||
${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE Qt6::QMock3Plugin Qt6::QMock4Plugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(manual_genex QMock1Plugin QMock2Plugin QMock3Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE $<1:Qt6::QMock3Plugin> $<0:Qt6::QMock4Plugin>
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(blacklist QMock1Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
EXCLUDE Qt6::QMock2Plugin Qt6::QMock3Plugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(blacklist_genex QMock1Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
EXCLUDE $<1:Qt6::QMock2Plugin> $<1:Qt6::QMock3Plugin> $<0:Qt6::QMock1Plugin>
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(override QMock3Plugin QMock4Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE_BY_TYPE mockplugin Qt6::QMock3Plugin Qt6::QMock4Plugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(override_genex QMock3Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE_BY_TYPE mockplugin $<1:Qt6::QMock3Plugin> $<0:Qt6::QMock4Plugin>
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
create_test_executable(override_mix QMock2Plugin QMock3Plugin ${import_mode})
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE Qt6::QMock2Plugin
|
||||
INCLUDE_BY_TYPE mockplugin Qt6::QMock3Plugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
if(NOT WIN32)
|
||||
# Compiling an empty static array fails on Windows.
|
||||
@ -116,6 +125,7 @@ foreach(import_mode "" "FINALIZER_MODE")
|
||||
qt_import_plugins(${target}
|
||||
EXCLUDE_BY_TYPE mockplugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
endif()
|
||||
|
||||
create_test_executable(none_mix QMock3Plugin QMock4Plugin ${import_mode})
|
||||
@ -123,6 +133,7 @@ foreach(import_mode "" "FINALIZER_MODE")
|
||||
INCLUDE Qt6::QMock3Plugin Qt6::QMock4Plugin
|
||||
EXCLUDE_BY_TYPE mockplugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
|
||||
# QMock5Plugin links against the Qt::MockPlugins3 module, which provides the default plugin
|
||||
# QMock6Plugin which is why it is pulled in.
|
||||
@ -130,10 +141,11 @@ foreach(import_mode "" "FINALIZER_MODE")
|
||||
qt_import_plugins(${target}
|
||||
INCLUDE_BY_TYPE mockplugin Qt6::QMock5Plugin
|
||||
)
|
||||
qt_finalize_target(${target})
|
||||
endforeach()
|
||||
|
||||
|
||||
# No call to qt_import_plugins() in finalizer mode means nothing will be linked.
|
||||
# No call to qt_finalize_target() in finalizer mode means nothing will be
|
||||
# linked.
|
||||
if(NOT WIN32)
|
||||
# Compiling an empty static array fails on Windows.
|
||||
create_test_executable(default_finalizer_missing_import_call FINALIZER_MODE)
|
||||
@ -145,18 +157,18 @@ create_test_executable(default_finalizer
|
||||
QMock3Plugin # TODO: Should not be linked based on .pro file, see QTBUG-93501
|
||||
FINALIZER_MODE)
|
||||
qt_import_plugins(${target})
|
||||
qt_finalize_target(${target})
|
||||
|
||||
# Check that plugin importing with manual finalization works.
|
||||
# Check that plugin importing with the qt_add_executable wrapper and manual finalization mode works.
|
||||
create_test_executable(default_qt_add_executable_manually_finalized
|
||||
QMock1Plugin QMock2Plugin
|
||||
QMock3Plugin # TODO: Should not be linked based on .pro file, see QTBUG-93501
|
||||
FINALIZER_MODE QT_WRAPPER
|
||||
ADD_EXECUTABLE_ARGS MANUAL_FINALIZATION)
|
||||
|
||||
qt_finalize_target(${target})
|
||||
|
||||
# Check that plugin importing with automatic finalization works when the CMake version is high
|
||||
# enough.
|
||||
# Check that plugin importing with automatic deferred finalization works when the CMake version is
|
||||
# high enough.
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
|
||||
create_test_executable(default_qt_add_executable_auto_finalized
|
||||
QMock1Plugin QMock2Plugin
|
||||
|
Loading…
Reference in New Issue
Block a user