diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake index 5750437594..fdc4981c3f 100644 --- a/src/corelib/Qt6AndroidMacros.cmake +++ b/src/corelib/Qt6AndroidMacros.cmake @@ -529,6 +529,7 @@ function(qt6_android_add_apk_target target) set_property(GLOBAL APPEND PROPERTY _qt_apk_targets ${target}) _qt_internal_collect_apk_dependencies_defer() + _qt_internal_collect_apk_imported_dependencies_defer("${target}") endfunction() function(_qt_internal_create_global_android_targets) @@ -654,6 +655,81 @@ function(_qt_internal_collect_buildsystem_shared_libraries out_var subdir) set(${out_var} "${result}" PARENT_SCOPE) endfunction() +# This function collects all imported shared libraries that might be dependencies for +# the main apk targets. The actual collection is deferred until the target's directory scope +# is processed. +# The function requires CMake 3.21 or later. +function(_qt_internal_collect_apk_imported_dependencies_defer target) + # User opted-out of the functionality. + if(QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS) + return() + endif() + + get_target_property(target_source_dir "${target}" SOURCE_DIR) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.21") + cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${target_source_dir}\" + CALL _qt_internal_collect_apk_imported_dependencies \"${target}\")") + endif() +endfunction() + +# This function collects imported shared libraries that might be dependencies for +# the main apk targets. It stores their locations on a custom target property for the given target. +# The function requires CMake 3.21 or later. +function(_qt_internal_collect_apk_imported_dependencies target) + # User opted-out the functionality + if(QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS) + return() + endif() + + get_target_property(target_source_dir "${target}" SOURCE_DIR) + _qt_internal_collect_imported_shared_libraries_recursive(libs "${target_source_dir}") + list(REMOVE_DUPLICATES libs) + + foreach(lib IN LISTS libs) + list(APPEND extra_library_dirs "$") + endforeach() + + set_property(TARGET "${target}" APPEND PROPERTY + _qt_android_extra_library_dirs "${extra_library_dirs}" + ) +endfunction() + +# This function recursively walks the current directory and its parent directories to collect +# imported shared library targets. +# The recursion goes upwards instead of downwards because imported targets are usually not global, +# and we can't call get_target_property() on a target which is not available in the current +# directory or parent scopes. +# We also can't cache parent directories because the imported targets in a parent directory +# might change in-between collection calls. +# The function requires CMake 3.21 or later. +function(_qt_internal_collect_imported_shared_libraries_recursive out_var subdir) + set(result "") + + get_directory_property(imported_targets DIRECTORY "${subdir}" IMPORTED_TARGETS) + foreach(imported_target IN LISTS imported_targets) + get_target_property(target_type "${imported_target}" TYPE) + if(target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY") + # If the target has the _qt_package_version property set, it means it's an + # 'official' qt target like a module or plugin, so we don't want to add it + # to the list of extra paths to scan for in androiddeployqt, because they are + # already handled via the regular 'qt' code path in the androiddeployqt. + # Thus this will pick up only non-qt 3rd party targets. + get_target_property(qt_package_version "${imported_target}" _qt_package_version) + if(NOT qt_package_version) + list(APPEND result "${imported_target}") + endif() + endif() + endforeach() + + get_directory_property(parent_dir DIRECTORY "${subdir}" PARENT_DIRECTORY) + if(parent_dir) + _qt_internal_collect_imported_shared_libraries_recursive(result_inner "${parent_dir}") + endif() + + list(APPEND result ${result_inner}) + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() + # This function allows deciding whether apks should be built as part of the ALL target at first # add_executable call point, rather than when the 'apk' target is created as part of the # find_package(Core) call. diff --git a/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc index 4b759c649b..bef29a6a94 100644 --- a/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc +++ b/src/corelib/doc/src/cmake/cmake-configure-variables.qdoc @@ -225,6 +225,33 @@ resolving dependencies between libraries. Set \c QT_NO_COLLECT_BUILD_TREE_APK_DEPS to \c TRUE to disable this behavior. \sa {qt6_finalize_project}{qt_finalize_project()} +\sa {cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}{QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS} +*/ + +/*! +\page cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS.html +\ingroup cmake-variables-qtcore + +\title QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS +\target cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS + +\summary {Prevents collecting of imported targets during Android deployment.} + +\cmakevariablesince 6.5 +\preliminarycmakevariable +\cmakevariableandroidonly + +When using CMake version 3.21 or later, the build system collects the locations of +imported shared library targets that might be relevant for deployment. +The collected targets are those that are reachable from the the directory scope +of the currently processed executable target. That includes the target's source directory +scope and its parents. +The collected locations are passed to \l androiddeployqt for deployment consideration when +resolving dependencies between libraries. +Set \c QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS to \c TRUE to disable this behavior. + +\sa {qt6_finalize_project}{qt_finalize_project()} +\sa {cmake-variable-QT_NO_COLLECT_BUILD_TREE_APK_DEPS}{QT_NO_COLLECT_BUILD_TREE_APK_DEPS} */ /*! diff --git a/src/corelib/doc/src/cmake/qt_finalize_project.qdoc b/src/corelib/doc/src/cmake/qt_finalize_project.qdoc index 5cd6a9fdaf..beee18ed80 100644 --- a/src/corelib/doc/src/cmake/qt_finalize_project.qdoc +++ b/src/corelib/doc/src/cmake/qt_finalize_project.qdoc @@ -49,4 +49,5 @@ function: \snippet cmake-macros/examples.cmake qt_finalize_project_manual \sa {cmake-variable-QT_NO_COLLECT_BUILD_TREE_APK_DEPS}{QT_NO_COLLECT_BUILD_TREE_APK_DEPS} +\sa {cmake-variable-QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS}{QT_NO_COLLECT_IMPORTED_TARGET_APK_DEPS} */