Allow finalizers to be delayed to later in the same directory scope

Deferred CMake calls are executed in the order they are created.
Sometimes, a deferred call created after a call to qt_add_executable()
or qt_add_library() needs to be executed before target finalization.
For example, a file may be written using a deferred write, but the
finalizers might need that file to exist.

Provide an internal _qt_internal_delay_finalization_until_after()
command that can be called to let finalization know it has to defer
to later. Target finalizers will check an internal property for IDs
recorded by that command and will re-defer itself if it detects that
any of those haven't run yet.

Task-number: QTBUG-96290
Pick-to: 6.2
Change-Id: Ia791e99339bab351eff0d675a552393e524490e8
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
bb10
Craig Scott 2021-09-13 15:54:00 +10:00
parent 2f6d572dad
commit 4f96af37b2
1 changed files with 27 additions and 0 deletions

View File

@ -609,7 +609,34 @@ function(_qt_internal_finalize_executable target)
set_target_properties(${target} PROPERTIES _qt_executable_is_finalized TRUE)
endfunction()
# If a task needs to run before any targets are finalized in the current directory
# scope, call this function and pass the ID of that task as the argument.
function(_qt_internal_delay_finalization_until_after defer_id)
set_property(DIRECTORY APPEND PROPERTY qt_internal_finalizers_wait_for_ids "${defer_id}")
endfunction()
function(qt6_finalize_target target)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
cmake_language(DEFER GET_CALL_IDS ids_queued)
get_directory_property(wait_for_ids qt_internal_finalizers_wait_for_ids)
while(wait_for_ids)
list(GET wait_for_ids 0 id_to_wait_for)
if(id_to_wait_for IN_LIST ids_queued)
# Something else needs to run before we finalize targets.
# Try again later by re-deferring ourselves, which effectively
# puts us at the end of the current list of deferred actions.
cmake_language(EVAL CODE "cmake_language(DEFER CALL ${CMAKE_CURRENT_FUNCTION} ${ARGV})")
set_directory_properties(PROPERTIES
qt_internal_finalizers_wait_for_ids "${wait_for_ids}"
)
return()
endif()
list(POP_FRONT wait_for_ids)
endwhile()
# No other deferred tasks to wait for
set_directory_properties(PROPERTIES qt_internal_finalizers_wait_for_ids "")
endif()
if(NOT TARGET "${target}")
message(FATAL_ERROR "No target '${target}' found in current scope.")
endif()