summaryrefslogtreecommitdiffstats
path: root/src/corelib/Qt6AndroidMacros.cmake
diff options
context:
space:
mode:
authorAlexey Edelev <alexey.edelev@qt.io>2021-08-17 16:25:03 +0200
committerAlexey Edelev <alexey.edelev@qt.io>2021-09-09 21:49:37 +0200
commitd20f4ae706559fb7de8db9dd4845f7ce3936061a (patch)
treecd2729521d7aaf72be595de5be0be35f2473b7a5 /src/corelib/Qt6AndroidMacros.cmake
parent2b8a6d026d2a9fed48847d9759a1b07ec34418a1 (diff)
Support deploying of libraries from a build tree when building android apk
If the project consists of an executable and multiple libraries that are linked to the executable, currently you need to specify them manually using QT_ANDROID_EXTRA_LIBS target property. This automates deploying of the libraries that are a part of the project build tree. _qt_internal_collect_target_apk_dependencies collects all the known non-imported shared libraries from the project build tree. When running androiddeployqt we specify extra library directories that point to the collected library locations in build tree, to help androiddeployqt resolve shared libraries that are build as a part of the project. The described procedure is running automatically if CMake version is greater than or equal to 3.18 is. For the CMake versions less than 3.18 users need to call a new public qt_finalize_project function at the end of project's top-level CMakeLists.txt Task-number: QTBUG-94714 Change-Id: I400ca4e49e940cfc25ae90d65372e79825bee55a Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/corelib/Qt6AndroidMacros.cmake')
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake131
1 files changed, 123 insertions, 8 deletions
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index 3640624aa3..144a082c6f 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -19,6 +19,15 @@ endfunction()
# Generate the deployment settings json file for a cmake target.
function(qt6_android_generate_deployment_settings target)
+ # Avoid calling the function twice
+ get_target_property(is_called ${target} _qt_is_android_generate_deployment_settings_called)
+ if(is_called)
+ return()
+ endif()
+ set_target_properties(${target} PROPERTIES
+ _qt_is_android_generate_deployment_settings_called TRUE
+ )
+
# Information extracted from mkspecs/features/android/android_deployment_settings.prf
if (NOT TARGET ${target})
message(SEND_ERROR "${target} is not a cmake target")
@@ -140,12 +149,12 @@ function(qt6_android_generate_deployment_settings target)
endif()
# package source dir
- get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
- if (android_package_source_dir)
- file(TO_CMAKE_PATH "${android_package_source_dir}" android_package_source_dir_native)
- string(APPEND file_contents
- " \"android-package-source-directory\": \"${android_package_source_dir_native}\",\n")
- endif()
+ set(android_package_source_dir_genex
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_PACKAGE_SOURCE_DIR>")
+ string(APPEND file_contents
+ "$<$<BOOL:${android_package_source_dir_genex}>:"
+ " \"android-package-source-directory\": \"${android_package_source_dir_genex}\"\,\n"
+ ">")
# version code
get_target_property(android_version_code ${target} QT_ANDROID_VERSION_CODE)
@@ -235,13 +244,34 @@ function(qt6_android_generate_deployment_settings target)
foreach(prefix IN LISTS CMAKE_FIND_ROOT_PATH)
if (NOT "${prefix}" STREQUAL "${qt_android_install_dir_native}"
AND NOT "${prefix}" STREQUAL "${android_ndk_root_native}")
- list(APPEND extra_prefix_list \"${prefix}\")
+ list(APPEND extra_prefix_list "\"${prefix}\"")
endif()
endforeach()
string (REPLACE ";" "," extra_prefix_list "${extra_prefix_list}")
string(APPEND file_contents
" \"extraPrefixDirs\" : [ ${extra_prefix_list} ],\n")
+ # Extra library paths that could be used as a dependency lookup path by androiddeployqt.
+ #
+ # Unlike 'extraPrefixDirs', the 'extraLibraryDirs' key doesn't expect the 'lib' subfolder
+ # when looking for dependencies.
+ set(extra_library_dirs_property_genex
+ "$<TARGET_PROPERTY:${target},_qt_android_extra_library_dirs>"
+ )
+ set(extra_library_dirs_add_quote_genex
+ "$<$<BOOL:${extra_library_dirs_property_genex}>:\">"
+ )
+ string(JOIN "" extra_library_dirs
+ "${extra_library_dirs_add_quote_genex}"
+ "$<JOIN:"
+ "$<GENEX_EVAL:${extra_library_dirs_property_genex}>,"
+ "\",\""
+ ">"
+ "${extra_library_dirs_add_quote_genex}"
+ )
+ string(APPEND file_contents
+ " \"extraLibraryDirs\" : [ ${extra_library_dirs} ],\n")
+
if(QT_FEATURE_zstd)
set(is_zstd_enabled "true")
else()
@@ -261,7 +291,7 @@ function(qt6_android_generate_deployment_settings target)
# content end
string(APPEND file_contents "}\n")
- file(WRITE ${deploy_file} ${file_contents})
+ file(GENERATE OUTPUT ${deploy_file} CONTENT ${file_contents})
set_target_properties(${target}
PROPERTIES
@@ -358,6 +388,8 @@ function(qt6_android_add_apk_target target)
COMMENT "Creating APK for ${target}"
)
endif()
+ set_property(GLOBAL APPEND PROPERTY _qt_apk_targets ${target})
+ _qt_internal_collect_target_apk_dependencies_defer(${target})
endfunction()
function(_qt_internal_create_global_apk_target)
@@ -371,6 +403,89 @@ function(_qt_internal_create_global_apk_target)
endif()
endfunction()
+# The function collects all known non-imported shared libraries that are created in the build tree.
+# It uses the CMake DEFER CALL feature if the CMAKE_VERSION is greater
+# than or equal to 3.18.
+# Note: Users that use cmake version less that 3.18 need to call qt_finalize_project
+# in the end of a project's top-level CMakeLists.txt.
+function(_qt_internal_collect_target_apk_dependencies_defer target)
+ # User opted-out the functionality
+ if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
+ return()
+ endif()
+
+ get_property(is_called GLOBAL PROPERTY _qt_is_collect_target_apk_dependencies_defer_called)
+ if(is_called) # Already scheduled
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_is_collect_target_apk_dependencies_defer_called TRUE)
+
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\"
+ CALL _qt_internal_collect_target_apk_dependencies ${target})")
+ else()
+ # User don't want to see the warning
+ if(NOT QT_NO_WARN_BUILD_TREE_APK_DEPS)
+ message(WARNING "CMake version you use is less than 3.18. APK dependencies, that are a"
+ " part of the project tree, might not be collected correctly."
+ " Please call qt_finalize_project in the end of a project's top-level"
+ " CMakeLists.txt file to make sure that all the APK dependencies are"
+ " collected correctly."
+ " You can pass -DQT_NO_WARN_BUILD_TREE_APK_DEPS=ON when configuring the project"
+ " to silence the warning.")
+ endif()
+ endif()
+endfunction()
+
+# The function collects shared libraries from the build system tree, that might be dependencies for
+# the main apk targets.
+function(_qt_internal_collect_target_apk_dependencies target)
+ # User opted-out the functionality
+ if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
+ return()
+ endif()
+
+ get_property(is_called GLOBAL PROPERTY _qt_is_collect_target_apk_dependencies_called)
+ if(is_called)
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_is_collect_target_apk_dependencies_called TRUE)
+
+ get_property(apk_targets GLOBAL PROPERTY _qt_apk_targets)
+
+ _qt_internal_collect_buildsystem_shared_libraries(libs "${CMAKE_SOURCE_DIR}")
+
+ foreach(lib IN LISTS libs)
+ if(NOT lib IN_LIST apk_targets)
+ list(APPEND extra_prefix_dirs "$<TARGET_FILE_DIR:${lib}>")
+ endif()
+ endforeach()
+
+ set_target_properties(${target} PROPERTIES _qt_android_extra_library_dirs "${extra_prefix_dirs}")
+endfunction()
+
+# The function recursively goes through the project subfolders and collects targets that supposed to
+# be shared libraries of any kind.
+function(_qt_internal_collect_buildsystem_shared_libraries out_var subdir)
+ set(result "")
+ get_directory_property(buildsystem_targets DIRECTORY ${subdir} BUILDSYSTEM_TARGETS)
+ foreach(buildsystem_target IN LISTS buildsystem_targets)
+ if(buildsystem_target AND TARGET ${buildsystem_target})
+ get_target_property(target_type ${buildsystem_target} TYPE)
+ if(target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
+ list(APPEND result ${buildsystem_target})
+ endif()
+ endif()
+ endforeach()
+
+ get_directory_property(subdirs DIRECTORY "${subdir}" SUBDIRECTORIES)
+ foreach(dir IN LISTS subdirs)
+ _qt_internal_collect_buildsystem_shared_libraries(result_inner "${dir}")
+ endforeach()
+ 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.