CMake: Promote all targets to global within a scope when possible

CMake 3.21 introduced a new IMPORTED_TARGETS directory property which
we can use to promote all imported targets within a scope to be
global.

This would cover transitive non-Qt imported targets which the Qt build
system does not know about and is thus a more complete solution
compared to promoting only Qt targets.

Run a finalizer at the end of the directory scope where
find_package(Qt6) is called to promote all imported targets within
that scope to global (when requested).

The old promotion method is disabled when the CMake version is new
enough.

Pick-to: 6.2
Task-number: QTBUG-92878
Task-number: QTBUG-94528
Change-Id: I533a3bd4186eba652f878ddd72c76118c2fd8bae
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Alexandru Croitor 2021-06-11 09:54:47 +02:00
parent 561fc8107f
commit 7f0f44f014
3 changed files with 39 additions and 3 deletions

View File

@ -105,3 +105,5 @@ if (_Qt_NOTFOUND_MESSAGE)
set(@INSTALL_CMAKE_NAMESPACE@_NOT_FOUND_MESSAGE "${_Qt_NOTFOUND_MESSAGE}")
set(@INSTALL_CMAKE_NAMESPACE@_FOUND False)
endif()
__qt_internal_defer_promote_targets_in_dir_scope_to_global()

View File

@ -124,7 +124,41 @@ function(__qt_internal_promote_target_to_global target)
endfunction()
function(__qt_internal_promote_target_to_global_checked target)
if(QT_PROMOTE_TO_GLOBAL_TARGETS)
# With CMake version 3.21 we use a different mechanism that allows us to promote all targets
# within a scope.
if(QT_PROMOTE_TO_GLOBAL_TARGETS AND CMAKE_VERSION VERSION_LESS 3.21)
__qt_internal_promote_target_to_global(${target})
endif()
endfunction()
function(__qt_internal_promote_targets_in_dir_scope_to_global)
# IMPORTED_TARGETS got added in 3.21.
if(CMAKE_VERSION VERSION_LESS 3.21)
return()
endif()
get_directory_property(targets IMPORTED_TARGETS)
foreach(target IN LISTS targets)
__qt_internal_promote_target_to_global(${target})
endforeach()
endfunction()
function(__qt_internal_promote_targets_in_dir_scope_to_global_checked)
if(QT_PROMOTE_TO_GLOBAL_TARGETS)
__qt_internal_promote_targets_in_dir_scope_to_global()
endif()
endfunction()
# This function ends up being called multiple times as part of a find_package(Qt6Foo) call,
# due sub-packages depending on the Qt6 package. Ensure the finalizer is ran only once per
# directory scope.
function(__qt_internal_defer_promote_targets_in_dir_scope_to_global)
get_directory_property(is_deferred _qt_promote_targets_is_deferred)
if(NOT is_deferred)
set_property(DIRECTORY PROPERTY _qt_promote_targets_is_deferred TRUE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
cmake_language(DEFER CALL __qt_internal_promote_targets_in_dir_scope_to_global_checked)
endif()
endif()
endfunction()

View File

@ -281,8 +281,8 @@ endmacro()
#
# The file also makes the targets global if the QT_PROMOTE_TO_GLOBAL_TARGETS property is set in the
# consuming project.
# Only the specified TARGETS are made global. Transitive 3rd party targets are not made global, due
# to limitations in CMake. See https://gitlab.kitware.com/cmake/cmake/-/issues/22291
# When using a CMake version lower than 3.21, only the specified TARGETS are made global.
# E.g. transitive non-Qt 3rd party targets of the specified targets are not made global.
#
# EXPORT_NAME_PREFIX:
# The portion of the file name before AdditionalTargetInfo.cmake