summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/QtFindPackageHelpers.cmake3
-rw-r--r--cmake/QtPluginHelpers.cmake2
-rw-r--r--cmake/QtPublicTargetHelpers.cmake14
-rw-r--r--cmake/QtPublicWalkLibsHelpers.cmake5
-rw-r--r--cmake/QtResourceHelpers.cmake4
-rw-r--r--cmake/QtScopeFinalizerHelpers.cmake3
-rw-r--r--cmake/QtTargetHelpers.cmake135
-rw-r--r--cmake/QtToolHelpers.cmake5
-rw-r--r--tests/auto/cmake/CMakeLists.txt4
-rw-r--r--tests/auto/cmake/test_global_promotion/CMakeLists.txt13
-rw-r--r--tests/auto/cmake/test_global_promotion/subdir_with_global_qt/CMakeLists.txt14
-rw-r--r--tests/auto/cmake/test_global_promotion/subdir_with_local_qt/CMakeLists.txt12
12 files changed, 197 insertions, 17 deletions
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index 1853240f22..fca039549e 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -159,8 +159,7 @@ macro(qt_find_package)
qt_internal_should_not_promote_package_target_to_global(
"${qt_find_package_target_name}" should_not_promote)
if(NOT is_global AND NOT should_not_promote)
- set_property(TARGET ${qt_find_package_target_name} PROPERTY
- IMPORTED_GLOBAL TRUE)
+ __qt_internal_promote_target_to_global(${qt_find_package_target_name})
qt_find_package_promote_targets_to_global_scope(
"${qt_find_package_target_name}")
endif()
diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake
index c4e0df4415..a7d2720ee4 100644
--- a/cmake/QtPluginHelpers.cmake
+++ b/cmake/QtPluginHelpers.cmake
@@ -343,7 +343,7 @@ function(qt_internal_add_plugin target)
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
qt_internal_export_additional_targets_file(
- TARGETS ${target}
+ TARGETS ${target} ${plugin_init_target}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
CONFIG_INSTALL_DIR "${config_install_dir}")
diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake
index 3804b18ac4..70e6c85b1a 100644
--- a/cmake/QtPublicTargetHelpers.cmake
+++ b/cmake/QtPublicTargetHelpers.cmake
@@ -114,3 +114,17 @@ function(__qt_internal_collect_resource_objects_recursively out_var target initi
endforeach()
set(${out_var} "${resource_targets}" PARENT_SCOPE)
endfunction()
+
+function(__qt_internal_promote_target_to_global target)
+ get_property(is_global TARGET ${target} PROPERTY IMPORTED_GLOBAL)
+ if(NOT is_global)
+ message(DEBUG "Promoting target to global: '${target}'")
+ set_property(TARGET ${target} PROPERTY IMPORTED_GLOBAL TRUE)
+ endif()
+endfunction()
+
+function(__qt_internal_promote_target_to_global_checked target)
+ if(QT_PROMOTE_TO_GLOBAL_TARGETS)
+ __qt_internal_promote_target_to_global(${target})
+ endif()
+endfunction()
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
index 963c15d4c6..19eef91356 100644
--- a/cmake/QtPublicWalkLibsHelpers.cmake
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
@@ -222,14 +222,13 @@ function(__qt_internal_walk_libs
endif()
get_property(is_imported TARGET ${lib_target_unaliased} PROPERTY IMPORTED)
- get_property(is_global TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL)
# Allow opting out of promotion. This is useful in certain corner cases
# like with WrapLibClang and Threads in qttools.
qt_internal_should_not_promote_package_target_to_global(
"${lib_target_unaliased}" should_not_promote)
- if(NOT is_global AND is_imported AND NOT should_not_promote)
- set_property(TARGET ${lib_target_unaliased} PROPERTY IMPORTED_GLOBAL TRUE)
+ if(is_imported AND NOT should_not_promote)
+ __qt_internal_promote_target_to_global(${lib_target_unaliased})
endif()
endif()
elseif("${lib_target}" MATCHES "^Qt::(.*)")
diff --git a/cmake/QtResourceHelpers.cmake b/cmake/QtResourceHelpers.cmake
index 3c719d1dd0..4b7d81cc7f 100644
--- a/cmake/QtResourceHelpers.cmake
+++ b/cmake/QtResourceHelpers.cmake
@@ -21,6 +21,10 @@ function(qt_internal_add_resource target resourceName)
EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets"
DESTINATION "${INSTALL_LIBDIR}"
)
+ qt_internal_add_targets_to_additional_targets_export_file(
+ TARGETS ${out_targets}
+ EXPORT_NAME_PREFIX "${INSTALL_CMAKE_NAMESPACE}${target}"
+ )
qt_internal_record_rcc_object_files("${target}" "${out_targets}"
INSTALL_DIRECTORY "${INSTALL_LIBDIR}")
diff --git a/cmake/QtScopeFinalizerHelpers.cmake b/cmake/QtScopeFinalizerHelpers.cmake
index 59e89cc9e2..6dae635ba2 100644
--- a/cmake/QtScopeFinalizerHelpers.cmake
+++ b/cmake/QtScopeFinalizerHelpers.cmake
@@ -74,6 +74,9 @@ function(qt_watch_current_list_dir variable access value current_list_file stack
qt_finalize_plugin(${a1} ${a2} ${a3} ${a4} ${a5} ${a6} ${a7} ${a8} ${a9})
elseif(func STREQUAL "qt_internal_finalize_app")
qt_internal_finalize_app(${a1} ${a2} ${a3} ${a4} ${a5} ${a6} ${a7} ${a8} ${a9})
+ elseif(func STREQUAL "qt_internal_export_additional_targets_file_finalizer")
+ qt_internal_export_additional_targets_file_finalizer(
+ ${a1} ${a2} ${a3} ${a4} ${a5} ${a6} ${a7} ${a8} ${a9})
else()
message(FATAL_ERROR "qt_watch_current_list_dir doesn't know about ${func}. Consider adding it.")
endif()
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index cc8bfde85f..be1cf5e2da 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -264,9 +264,26 @@ function(qt_internal_check_directory_or_type name dir type default result_var)
endif()
endfunction()
+macro(qt_internal_get_export_additional_targets_keywords option_args single_args multi_args)
+ set(${option_args}
+ )
+ set(${single_args}
+ EXPORT_NAME_PREFIX
+ )
+ set(${multi_args}
+ TARGETS
+ TARGET_EXPORT_NAMES
+ )
+endmacro()
+
# Create a Qt*AdditionalTargetInfo.cmake file that is included by Qt*Config.cmake
# and sets IMPORTED_*_<CONFIG> properties on the exported targets.
#
+# 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
+#
# EXPORT_NAME_PREFIX:
# The portion of the file name before AdditionalTargetInfo.cmake
# CONFIG_INSTALL_DIR:
@@ -283,14 +300,75 @@ endfunction()
# TARGET_EXPORT_NAMES = Qt6::qmljs
#
function(qt_internal_export_additional_targets_file)
- cmake_parse_arguments(arg "" "EXPORT_NAME_PREFIX;CONFIG_INSTALL_DIR"
- "TARGETS;TARGET_EXPORT_NAMES" ${ARGN})
+ qt_internal_get_export_additional_targets_keywords(option_args single_args multi_args)
+ cmake_parse_arguments(arg
+ "${option_args}"
+ "${single_args};CONFIG_INSTALL_DIR"
+ "${multi_args}"
+ ${ARGN})
+
+ qt_internal_append_export_additional_targets()
+
+ set_property(GLOBAL APPEND PROPERTY _qt_export_additional_targets_ids "${id}")
+ set_property(GLOBAL APPEND
+ PROPERTY _qt_export_additional_targets_export_name_prefix_${id} "${arg_EXPORT_NAME_PREFIX}")
+ set_property(GLOBAL APPEND
+ PROPERTY _qt_export_additional_targets_config_install_dir_${id} "${arg_CONFIG_INSTALL_DIR}")
+
+ qt_add_list_file_finalizer(qt_internal_export_additional_targets_file_finalizer)
+endfunction()
+
+function(qt_internal_get_export_additional_targets_id export_name out_var)
+ string(MAKE_C_IDENTIFIER "${export_name}" id)
+ set(${out_var} "${id}" PARENT_SCOPE)
+endfunction()
+
+# Uses outer-scope variables to keep the implementation less verbose.
+macro(qt_internal_append_export_additional_targets)
+ qt_internal_validate_export_additional_targets(
+ EXPORT_NAME_PREFIX "${arg_EXPORT_NAME_PREFIX}"
+ TARGETS ${arg_TARGETS}
+ TARGET_EXPORT_NAMES ${arg_TARGET_EXPORT_NAMES})
+
+ qt_internal_get_export_additional_targets_id("${arg_EXPORT_NAME_PREFIX}" id)
+
+ set_property(GLOBAL APPEND
+ PROPERTY _qt_export_additional_targets_${id} "${arg_TARGETS}")
+ set_property(GLOBAL APPEND
+ PROPERTY _qt_export_additional_target_export_names_${id} "${arg_TARGET_EXPORT_NAMES}")
+endmacro()
+
+# Can be called to add additional targets to the file after the initial setup call.
+# Used for resources.
+function(qt_internal_add_targets_to_additional_targets_export_file)
+ qt_internal_get_export_additional_targets_keywords(option_args single_args multi_args)
+ cmake_parse_arguments(arg
+ "${option_args}"
+ "${single_args}"
+ "${multi_args}"
+ ${ARGN})
+
+ qt_internal_append_export_additional_targets()
+endfunction()
+
+function(qt_internal_validate_export_additional_targets)
+ qt_internal_get_export_additional_targets_keywords(option_args single_args multi_args)
+ cmake_parse_arguments(arg
+ "${option_args}"
+ "${single_args}"
+ "${multi_args}"
+ ${ARGN})
+
+ if(NOT arg_EXPORT_NAME_PREFIX)
+ message(FATAL_ERROR "qt_internal_validate_export_additional_targets: "
+ "Missing EXPORT_NAME_PREFIX argument.")
+ endif()
list(LENGTH arg_TARGETS num_TARGETS)
list(LENGTH arg_TARGET_EXPORT_NAMES num_TARGET_EXPORT_NAMES)
if(num_TARGET_EXPORT_NAMES GREATER 0)
if(NOT num_TARGETS EQUAL num_TARGET_EXPORT_NAMES)
- message(FATAL_ERROR "qt_internal_export_additional_targets_file: "
+ message(FATAL_ERROR "qt_internal_validate_export_additional_targets: "
"TARGET_EXPORT_NAMES is set but has ${num_TARGET_EXPORT_NAMES} elements while "
"TARGETS has ${num_TARGETS} elements. "
"They must contain the same number of elements.")
@@ -299,6 +377,34 @@ function(qt_internal_export_additional_targets_file)
set(arg_TARGET_EXPORT_NAMES ${arg_TARGETS})
endif()
+ set(arg_TARGETS "${arg_TARGETS}" PARENT_SCOPE)
+ set(arg_TARGET_EXPORT_NAMES "${arg_TARGET_EXPORT_NAMES}" PARENT_SCOPE)
+endfunction()
+
+# The finalizer might be called multiple times in the same scope, but only the first one will
+# process all the ids.
+function(qt_internal_export_additional_targets_file_finalizer)
+ get_property(ids GLOBAL PROPERTY _qt_export_additional_targets_ids)
+
+ foreach(id ${ids})
+ qt_internal_export_additional_targets_file_handler("${id}")
+ endforeach()
+
+ set_property(GLOBAL PROPERTY _qt_export_additional_targets_ids "")
+endfunction()
+
+function(qt_internal_export_additional_targets_file_handler id)
+ get_property(arg_EXPORT_NAME_PREFIX GLOBAL PROPERTY
+ _qt_export_additional_targets_export_name_prefix_${id})
+ get_property(arg_CONFIG_INSTALL_DIR GLOBAL PROPERTY
+ _qt_export_additional_targets_config_install_dir_${id})
+ get_property(arg_TARGETS GLOBAL PROPERTY
+ _qt_export_additional_targets_${id})
+ get_property(arg_TARGET_EXPORT_NAMES GLOBAL PROPERTY
+ _qt_export_additional_target_export_names_${id})
+
+ list(LENGTH arg_TARGETS num_TARGETS)
+
# Determine the release configurations we're currently building
if(QT_GENERATOR_IS_MULTI_CONFIG)
set(active_configurations ${CMAKE_CONFIGURATION_TYPES})
@@ -337,18 +443,33 @@ if(NOT DEFINED QT_DEFAULT_IMPORT_CONFIGURATION)
set(QT_DEFAULT_IMPORT_CONFIGURATION ${uc_default_cfg})
endif()
")
+
math(EXPR n "${num_TARGETS} - 1")
foreach(i RANGE ${n})
list(GET arg_TARGETS ${i} target)
list(GET arg_TARGET_EXPORT_NAMES ${i} target_export_name)
- get_target_property(target_type ${target} TYPE)
- if(target_type STREQUAL "INTERFACE_LIBRARY")
- continue()
- endif()
+
set(full_target ${target_export_name})
if(NOT full_target MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::")
string(PREPEND full_target "${QT_CMAKE_EXPORT_NAMESPACE}::")
endif()
+
+ # Tools are already made global unconditionally in QtFooToolsConfig.cmake.
+ # And the
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "EXECUTABLE")
+ string(APPEND content
+ "__qt_internal_promote_target_to_global_checked(${full_target})\n")
+ endif()
+
+ # INTERFACE libraries don't have IMPORTED_LOCATION-like properties.
+ # OBJECT libraries have properties like IMPORTED_OBJECTS instead.
+ # Skip the rest of the procesing for those.
+ if(target_type STREQUAL "INTERFACE_LIBRARY" OR target_type STREQUAL "OBJECT_LIBRARY")
+ continue()
+ endif()
+
+ # FIXME: Don't add IMPORTED_SOLIB and IMPORTED_SONAME properties for executables.
set(properties_retrieved TRUE)
if(NOT "${uc_release_cfg}" STREQUAL "")
string(APPEND content "get_target_property(_qt_imported_location ${full_target} IMPORTED_LOCATION_${uc_release_cfg})\n")
diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake
index 24ab9e0162..4274e622a4 100644
--- a/cmake/QtToolHelpers.cmake
+++ b/cmake/QtToolHelpers.cmake
@@ -321,10 +321,7 @@ function(qt_export_tools module_name)
endif()
set(extra_cmake_statements "${extra_cmake_statements}
if (NOT QT_NO_CREATE_TARGETS)
- get_property(is_global TARGET ${INSTALL_CMAKE_NAMESPACE}::${tool_name} PROPERTY IMPORTED_GLOBAL)
- if(NOT is_global)
- set_property(TARGET ${INSTALL_CMAKE_NAMESPACE}::${tool_name} PROPERTY IMPORTED_GLOBAL TRUE)
- endif()
+ __qt_internal_promote_target_to_global(${INSTALL_CMAKE_NAMESPACE}::${tool_name})
endif()
")
list(APPEND tool_targets "${QT_CMAKE_EXPORT_NAMESPACE}::${tool_name}")
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index b95c530640..8852c7e68b 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -247,6 +247,10 @@ set_tests_properties(test_import_plugins PROPERTIES FIXTURES_REQUIRED build_mock
_qt_internal_test_expect_pass(test_versionless_targets)
+if(NOT NO_GUI)
+ _qt_internal_test_expect_pass(test_global_promotion)
+endif()
+
_qt_internal_test_expect_pass(test_add_resources_binary_generated
BINARY test_add_resources_binary_generated)
diff --git a/tests/auto/cmake/test_global_promotion/CMakeLists.txt b/tests/auto/cmake/test_global_promotion/CMakeLists.txt
new file mode 100644
index 0000000000..c59dece81e
--- /dev/null
+++ b/tests/auto/cmake/test_global_promotion/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.14)
+
+project(global_promotion)
+
+add_subdirectory(subdir_with_local_qt)
+add_subdirectory(subdir_with_global_qt)
+
+set(file_path "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+file(GENERATE OUTPUT "${file_path}" CONTENT "int main() { return 0; }")
+add_executable(exe main.cpp)
+
+# The Qt targets found in the 2nd child directory scope should be available in this scope.
+target_link_libraries(exe PRIVATE lib_global_qt)
diff --git a/tests/auto/cmake/test_global_promotion/subdir_with_global_qt/CMakeLists.txt b/tests/auto/cmake/test_global_promotion/subdir_with_global_qt/CMakeLists.txt
new file mode 100644
index 0000000000..a8808a8c83
--- /dev/null
+++ b/tests/auto/cmake/test_global_promotion/subdir_with_global_qt/CMakeLists.txt
@@ -0,0 +1,14 @@
+message(STATUS "Entered subdir_with_global_qt subdirectory")
+
+set(file_path "${CMAKE_CURRENT_BINARY_DIR}/lib.cpp")
+file(GENERATE OUTPUT "${file_path}" CONTENT "int foo() { return 42; }")
+add_library(lib_global_qt STATIC "${file_path}")
+
+# These Qt targets will be available in all scopes of the project.
+# The previous local targets are simply shadowed.
+set(QT_PROMOTE_TO_GLOBAL_TARGETS ON)
+find_package(Qt6 REQUIRED COMPONENTS Gui)
+
+target_link_libraries(lib_global_qt PRIVATE Qt6::Gui)
+
+message(STATUS "Exiting subdir_with_global_qt subdirectory")
diff --git a/tests/auto/cmake/test_global_promotion/subdir_with_local_qt/CMakeLists.txt b/tests/auto/cmake/test_global_promotion/subdir_with_local_qt/CMakeLists.txt
new file mode 100644
index 0000000000..1bed5a2f99
--- /dev/null
+++ b/tests/auto/cmake/test_global_promotion/subdir_with_local_qt/CMakeLists.txt
@@ -0,0 +1,12 @@
+message(STATUS "Entered subdir_with_local_qt subdirectory")
+
+set(file_path "${CMAKE_CURRENT_BINARY_DIR}/lib.cpp")
+file(GENERATE OUTPUT "${file_path}" CONTENT "int foo() { return 42; }")
+add_library(lib_local_qt STATIC "${file_path}")
+
+# These Qt targets will be local to this directory scope.
+find_package(Qt6 REQUIRED COMPONENTS Gui)
+
+target_link_libraries(lib_local_qt PRIVATE Qt6::Gui)
+
+message(STATUS "Exiting subdir_with_local_qt subdirectory")