qt6_finalize_executable(): Enable finalizers to be set per-target

Some plugins need to append additional processing to targets that use
them. This is most commonly needed for static builds to identify
additional plugins that need to be linked, but which cannot be
determined automatically by CMake as part of its transitive
dependency handling. Check for finalizers on directly linked targets
as a way to help automate common scenarios.

Because we need to lookup dependency targets and these may have
visibility limited to the depender target's scope, we now formally
document that finalizers should be called from the same scope as
the one in which the target was created. This was loosely expected
before, but is now made explicit.

Task-number: QTBUG-90819
Task-number: QTBUG-86669
Pick-to: 6.1
Change-Id: I065a3f3a4ab6eeff6a98a655835427949e2fe0f1
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Craig Scott 2021-02-15 18:59:08 +11:00
parent fe29159aad
commit 279ebfd487
2 changed files with 53 additions and 8 deletions

View File

@ -477,6 +477,47 @@ endfunction()
# This function is currently in Technical Preview.
# It's signature and behavior might change.
function(qt6_finalize_executable target)
# We can't evaluate generator expressions at configure time, so we can't
# ask for any transitive properties or even the full library dependency
# chain. We can still look at the immediate dependencies though and query
# any that are not expressed as generator expressions. For any we can
# identify as a CMake target known to the current scope, we can check if
# that target has a finalizer to be called. This is expected to cover the
# vast majority of use cases, since projects will typically link directly
# to Qt::* targets. For the cases where this isn't so, the project will be
# responsible for calling any relevant functions themselves instead of
# relying on these automatic finalization calls.
set(finalizers)
get_target_property(immediate_deps ${target} LINK_LIBRARIES)
if(immediate_deps)
foreach(dep IN LISTS immediate_deps)
if(NOT TARGET ${dep})
continue()
endif()
get_target_property(dep_finalizers ${dep}
INTERFACE_QT_EXECUTABLE_FINALIZERS
)
if(dep_finalizers)
list(APPEND finalizers ${dep_finalizers})
endif()
endforeach()
list(REMOVE_DUPLICATES finalizers)
endif()
if(finalizers)
if(CMAKE_VERSION VERSION_LESS 3.18)
# cmake_language() not available
message(WARNING
"Skipping module-specific finalizers for target ${target} "
"(requires CMake 3.18 or later)"
)
else()
foreach(finalizer_func IN LISTS finalizers)
cmake_language(CALL ${finalizer_func} ${target})
endforeach()
endif()
endif()
if(ANDROID)
qt6_android_generate_deployment_settings("${target}")
qt6_android_add_apk_target("${target}")

View File

@ -369,12 +369,12 @@ properties of the target. The finalization processing is implemented by the
\l{qt6_finalize_executable}{qt_finalize_executable()} command.
Finalization can occur either as part of this call or be deferred to sometime
after this command returns. When using CMake 3.19 or later, finalization is
automatically deferred to the end of the current directory scope. This gives the
caller an opportunity to modify properties of the created target before it is
finalized. When using CMake versions earlier than 3.19, automatic deferral isn't
supported. In that case, finalization is performed immediately before this
command returns.
after this command returns (but it should still be in the same directory scope).
When using CMake 3.19 or later, finalization is automatically deferred to the
end of the current directory scope. This gives the caller an opportunity to
modify properties of the created target before it is finalized. When using
CMake versions earlier than 3.19, automatic deferral isn't supported. In that
case, finalization is performed immediately before this command returns.
Regardless of the CMake version, the \c{MANUAL_FINALIZATION} keyword can be given to
indicate that you will explicitly call \l{qt6_finalize_executable}{qt_finalize_executable()}
@ -424,8 +424,12 @@ qt6_finalize_executable(target)
After a target is created, further processing or \e{finalization} steps are
commonly needed. The steps to perform depend on the platform and on various
properties of the target. This command implements the following, as appropriate
for the platform and target provided:
properties of the target. These steps are expected to be performed within the
same directory scope as the one in which the \c{target} was created, so this
command should also be called from that same directory scope.
This command implements the following, as appropriate for the platform and
target provided:
\list
\li When targeting Android, generate a deployment settings file for the target.