summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2021-05-20 13:38:30 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2021-06-16 13:22:17 +0200
commit561fc8107f38b93808343e35c62d7d06704f8eb6 (patch)
tree552b0084d0fbc20c9e19dbd6bd244e93b28a590f /cmake
parentd829d54a42393d797c5f6ab3b80e88df35fad1e4 (diff)
CMake: Allow promoting the Qt libraries to be global targets
User projects can set the QT_PROMOTE_TO_GLOBAL_TARGETS variable to true so that the various imported targets created by find_package(Qt6) are promoted to global targets. This would allow a project to find Qt packages in a subdirectory scope while using those Qt targets from a different scope. E.g. it fixes errors like CMake Error at CMakeLists.txt:5 (target_link_libraries): Error evaluating generator expression: $<TARGET_OBJECTS:Qt6::Widgets_resources_1> Objects of target "Qt6::Widgets_resources_1" referenced but no such target exists. when trying to use a static Qt from a sibling scope. Various 3rd party dependency targets (like Atomic or ZLIB) are not made global due to limitations in CMake, but as long as those targets are not mentioned directly, it shouldn't cause issues. The targets are made global in the generated QtFooAdditionalTargetInfo.cmake file. To ensure that resource object libraries promoted, the generation of the file has to be done at the end of the defining scope where qt_internal_export_additional_targets_file is called, which is achieved with a deferred finalizer. Replaced all occurrences of target promotion with a helper function which allows tracing of all promoted targets by specifying --log-level=debug to CMake. Pick-to: 6.2 Fixes: QTBUG-92878 Change-Id: Ic4ec03b0bc383d7e591a58c520c3974fbea746d2 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'cmake')
-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
8 files changed, 154 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}")