summaryrefslogtreecommitdiffstats
path: root/src/corelib/Qt6AndroidMacros.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/Qt6AndroidMacros.cmake')
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake216
1 files changed, 161 insertions, 55 deletions
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index aa0e5bfed24..ed97a42c83f 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -120,6 +120,29 @@ function(_qt_internal_generate_android_permissions_json out_result target)
set(${out_result} "${result}" PARENT_SCOPE)
endfunction()
+# Add the specific dynamic library as the dynamic feature for the Android application target.
+function(qt6_add_android_dynamic_features target)
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "FEATURE_TARGETS")
+ if(NOT QT_USE_ANDROID_MODERN_BUNDLE)
+ message(FATAL_ERROR "qt6_add_android_dynamic_features is only supported with"
+ " 'QT_USE_ANDROID_MODERN_BUNDLE' enabled.")
+ endif()
+ if(NOT TARGET ${target})
+ message(FATAL_ERROR "${target} is not a target. Cannot add the dynamic features.")
+ endif()
+ get_target_property(android_type ${target} _qt_android_target_type)
+ if(NOT android_type STREQUAL "APPLICATION")
+ message(FATAL_ERROR "${target} is not an android executable target."
+ " Cannot add the dynamic features.")
+ endif()
+ if(arg_FEATURE_TARGETS)
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_android_dynamic_features ${arg_FEATURE_TARGETS})
+ else()
+ message(WARNING "No dynamic features provided.")
+ endif()
+endfunction()
+
# Generate the deployment settings json file for a cmake target.
function(qt6_android_generate_deployment_settings target)
# Information extracted from mkspecs/features/android/android_deployment_settings.prf
@@ -324,8 +347,9 @@ function(qt6_android_generate_deployment_settings target)
__qt_internal_collect_plugin_library_files_v2("${target}" "${plugin_targets}" plugin_targets)
string(APPEND file_contents " \"android-deploy-plugins\":\"${plugin_targets}\",\n")
- _qt_internal_generate_android_permissions_json(permissions_json_array "${target}")
- string(APPEND file_contents " \"permissions\": ${permissions_json_array},\n")
+
+ _qt_internal_android_convert_permissions(permissions_genex ${target} JSON)
+ string(APPEND file_contents " \"permissions\": ${permissions_genex},\n")
# App binary
string(APPEND file_contents
@@ -415,44 +439,6 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
-function(_qt_internal_add_android_permission target)
- if(NOT TARGET ${target})
- message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})")
- endif()
-
- cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN})
-
- if(NOT arg_NAME)
- message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})")
- endif()
-
- set(permission_entry "${arg_NAME}")
-
- if(arg_ATTRIBUTES)
- # Permission with additional attributes
- list(LENGTH arg_ATTRIBUTES attributes_len)
- math(EXPR attributes_modulus "${attributes_len} % 2")
- if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0))
- message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES} must"
- " be name-value pairs (for example: minSdkVersion 30)")
- endif()
- # Combine name-value pairs
- set(index 0)
- set(attributes "")
- while(index LESS attributes_len)
- list(GET arg_ATTRIBUTES ${index} name)
- math(EXPR index "${index} + 1")
- list(GET arg_ATTRIBUTES ${index} value)
- string(APPEND attributes "android:${name}=\'${value}\' ")
- math(EXPR index "${index} + 1")
- endwhile()
- set(permission_entry "${permission_entry}\;${attributes}")
- endif()
-
- # Append the permission to the target's property
- set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}")
-endfunction()
-
function(qt6_add_android_permission target)
_qt_internal_add_android_permission(${ARGV})
endfunction()
@@ -519,18 +505,6 @@ function(qt6_android_add_apk_target target)
">"
)
- # Make global apk and aab targets depend on the current apk target.
- if(TARGET aab)
- add_dependencies(aab ${target}_make_aab)
- endif()
- if(TARGET aar)
- add_dependencies(aar ${target}_make_aar)
- endif()
- if(TARGET apk)
- add_dependencies(apk ${target}_make_apk)
- _qt_internal_create_global_apk_all_target_if_needed()
- endif()
-
_qt_internal_android_get_deployment_tool(deployment_tool)
# No need to use genex for the BINARY_DIR since it's read-only.
@@ -719,6 +693,10 @@ function(qt6_android_add_apk_target target)
)
add_dependencies(${target}_make_aab ${target}_prepare_apk_dir)
+ # Make global apk, aab, and aar targets depend on the respective targets.
+ _qt_internal_android_add_global_package_dependencies(${target})
+ _qt_internal_create_global_apk_all_target_if_needed()
+
if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
# When building per-ABI external projects we only need to copy ABI-specific libraries and
# resources to the "main" ABI android build folder.
@@ -1661,13 +1639,26 @@ endfunction()
# module and is executed implicitly when configuring user projects.
function(_qt_internal_android_executable_finalizer target)
set_property(TARGET ${target} PROPERTY _qt_android_executable_finalizer_called TRUE)
+ set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "EXECUTABLE")
_qt_internal_expose_android_package_source_dir_to_ide(${target})
_qt_internal_configure_android_multiabi_target("${target}")
qt6_android_generate_deployment_settings("${target}")
- qt6_android_add_apk_target("${target}")
+ if(QT_USE_ANDROID_MODERN_BUNDLE)
+ _qt_internal_android_generate_dynamic_feature_names("${target}")
+ _qt_internal_android_add_dynamic_feature_deployment("${target}")
+
+ _qt_internal_android_prepare_gradle_build("${target}")
+ _qt_internal_android_add_aux_deployment("${target}")
+
+ _qt_internal_collect_apk_dependencies_defer()
+ _qt_internal_collect_apk_imported_dependencies_defer("${target}")
+ else()
+ qt6_android_add_apk_target("${target}")
+ endif()
_qt_internal_android_create_runner_wrapper("${target}")
+ set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "")
endfunction()
# Helper to add the android executable finalizer.
@@ -1737,8 +1728,9 @@ function(_qt_internal_android_app_runner_arguments target out_runner_path out_ar
set(${out_runner_path} "${runner_dir}/qt-android-runner.py" PARENT_SCOPE)
_qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
+ _qt_internal_android_get_platform_tools_path(platform_tools)
set(${out_arguments}
- "--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb"
+ "--adb" "${platform_tools}/adb"
"--build-path" "${android_build_dir}"
"--apk" "${android_build_dir}/${target}.apk"
PARENT_SCOPE
@@ -1754,8 +1746,13 @@ function(_qt_internal_android_get_target_android_build_dir out_build_dir target)
endif()
endfunction()
+function(_qt_internal_android_get_target_deployment_dir out_deploy_dir target)
+ _qt_internal_android_get_target_android_build_dir(build_dir ${target})
+ set(${out_deploy_dir} "${build_dir}/app" PARENT_SCOPE)
+endfunction()
+
function(_qt_internal_expose_android_package_source_dir_to_ide target)
- get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ _qt_internal_android_get_package_source_dir(android_package_source_dir ${target})
if(android_package_source_dir)
get_target_property(target_source_dir ${target} SOURCE_DIR)
if(NOT IS_ABSOLUTE "${android_package_source_dir}")
@@ -1778,6 +1775,71 @@ function(_qt_internal_expose_android_package_source_dir_to_ide target)
endif()
endfunction()
+function(_qt_internal_android_add_aux_deployment target)
+ cmake_parse_arguments(arg "" "OUTPUT_TARGET_NAME;DEPLOYMENT_DIRECTORY" "EXTRA_ARGS" ${ARGN})
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ string(JOIN "" deployment_file
+ "$<GENEX_EVAL:"
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
+ ">"
+ )
+
+ _qt_internal_android_get_deployment_tool(deployment_tool)
+ if(arg_DEPLOYMENT_DIRECTORY)
+ set(deployment_dir "${arg_DEPLOYMENT_DIRECTORY}")
+ else()
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+ endif()
+
+ cmake_policy(PUSH)
+ if(POLICY CMP0116)
+ # Without explicitly setting this policy to NEW, we get a warning
+ # even though we ensure there's actually no problem here.
+ # See https://gitlab.kitware.com/cmake/cmake/-/issues/21959
+ cmake_policy(SET CMP0116 NEW)
+ set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR})
+ else()
+ set(relative_to_dir ${CMAKE_BINARY_DIR})
+ endif()
+
+ set(target_file_copy_relative_path
+ "libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${target}>"
+ "${deployment_dir}/${target_file_copy_relative_path}"
+ )
+
+ _qt_internal_android_get_use_terminal_for_deployment(uses_terminal)
+
+ # TODO: We use androiddeployqt to collect target depdenencies and produce the lib.xml file
+ # which autoloads the collected libraries. Should be done using GRE and transitive properties
+ # in the future.
+ set(libs_xml "${deployment_dir}/res/values/libs.xml")
+ add_custom_command(OUTPUT "${libs_xml}"
+ COMMAND ${copy_command}
+ COMMAND "${deployment_tool}"
+ --input "${deployment_file}"
+ --output "${deployment_dir}"
+ --builddir "${relative_to_dir}"
+ --aux-mode
+ ${arg_EXTRA_ARGS}
+ #TODO: Support signing
+ COMMENT "Deploying Android artifacts for ${target}"
+ DEPENDS "${target}" "${deployment_file}"
+ VERBATIM
+ ${uses_terminal}
+ )
+
+ if(NOT arg_OUTPUT_TARGET_NAME)
+ set(arg_OUTPUT_TARGET_NAME ${target}_android_deploy_aux)
+ endif()
+
+ add_custom_target(${arg_OUTPUT_TARGET_NAME} DEPENDS "${libs_xml}")
+
+ cmake_policy(POP)
+endfunction()
+
# Enables the terminal usage for the add_custom_command calls when verbose deployment is enabled.
function(_qt_internal_android_get_use_terminal_for_deployment out_var)
if(QT_ENABLE_VERBOSE_DEPLOYMENT)
@@ -1822,6 +1884,45 @@ function(_qt_internal_android_get_deployment_type_option out_var release_flag de
endif()
endfunction()
+# Returns the path to the android template directory, that are used by CMake
+# deployment procedures.
+function(_qt_internal_android_template_dir out_var)
+ if(PROJECT_NAME STREQUAL "QtBase" OR QT_SUPERBUILD)
+ set(${out_var} "${QtBase_SOURCE_DIR}/src/android/templates_cmake" PARENT_SCOPE)
+ else()
+ set(${out_var}
+ "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_DATA}/src/android/templates_cmake" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Return the path to the target template directory if it's set for the target.
+# Then this path is stored in the target QT_ANDROID_PACKAGE_SOURCE_DIR property
+# and can only be effectively read in android finalizers.
+function(_qt_internal_android_get_package_source_dir out_var target)
+ get_target_property(in_finalizer ${target} _qt_android_in_finalizer)
+ if(NOT in_finalizer)
+ message(FATAL_ERROR "The '_qt_internal_android_get_package_source_dir' function is"
+ " called outside the Android finalizer."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+ get_target_property(package_src_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ if(NOT package_src_dir)
+ set(package_src_dir "")
+ endif()
+ set(${out_var} "${package_src_dir}" PARENT_SCOPE)
+endfunction()
+
+# Add target_make_<apk|aab> as the depednecy for the respective global apk/aab
+# target.
+function(_qt_internal_android_add_global_package_dependencies target)
+ foreach(type apk aab aar)
+ # Make global apk and aab targets depend on the current apk target.
+ if(TARGET ${type} AND TARGET ${target}_make_${type})
+ add_dependencies(${type} ${target}_make_${type})
+ endif()
+ endforeach()
+endfunction()
+
function(_qt_internal_android_get_target_abis out_abis target)
get_target_property(target_abis ${target} QT_ANDROID_ABIS)
if(target_abis)
@@ -1840,5 +1941,10 @@ function(_qt_internal_android_get_target_abis out_abis target)
set(${out_abis} "${android_abis}" PARENT_SCOPE)
endfunction()
+# Returns the path to the Android platform-tools(adb is located there).
+function(_qt_internal_android_get_platform_tools_path out_var)
+ set(${out_var} "${ANDROID_SDK_ROOT}/platform-tools" PARENT_SCOPE)
+endfunction()
+
set(QT_INTERNAL_ANDROID_TARGET_BUILD_DIR_SUPPORT ON CACHE INTERNAL
"Indicates that Qt supports per-target Android build directories")