summaryrefslogtreecommitdiffstats
path: root/cmake/QtPlatformAndroid.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/QtPlatformAndroid.cmake')
-rw-r--r--cmake/QtPlatformAndroid.cmake371
1 files changed, 98 insertions, 273 deletions
diff --git a/cmake/QtPlatformAndroid.cmake b/cmake/QtPlatformAndroid.cmake
index dd76b1e81e..e4253b75d7 100644
--- a/cmake/QtPlatformAndroid.cmake
+++ b/cmake/QtPlatformAndroid.cmake
@@ -1,26 +1,22 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#
# Self contained Platform Settings for Android
#
-# Note: This file is used both by the internal and public builds.
+# Note: This file is used by the internal builds.
#
#
-# Public variables:
+# Variables:
# QT_ANDROID_JAR
# Location of the adroid sdk jar for java code
-# QT_ANDROID_APIVERSION
+# QT_ANDROID_API_VERSION
# Android API version
-# QT_ANDROID_SDK_BUILD_TOOLS_VERSION
-# Detected Android sdk build tools version
-#
-# Public functions:
-#
-# qt_android_generate_deployment_settings()
-# Generate the deployment settings json file for a cmake target.
#
if (NOT DEFINED ANDROID_SDK_ROOT)
- message(FATAL_ERROR "Please provide the location of the Android SDK directory via -DANDROID_SDK_ROOT=<path to Adndroid SDK>")
+ message(FATAL_ERROR "Please provide the location of the Android SDK directory via -DANDROID_SDK_ROOT=<path to Android SDK>")
endif()
if (NOT IS_DIRECTORY "${ANDROID_SDK_ROOT}")
@@ -40,28 +36,66 @@ function(qt_get_android_sdk_jar_for_api api out_jar_location)
endfunction()
# Minimum recommend android SDK api version
-set(QT_ANDROID_API_VERSION "android-28")
+set(QT_ANDROID_API_VERSION "android-33")
-# Locate android.jar
-set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_VERSION}/android.jar")
-if(NOT EXISTS "${QT_ANDROID_JAR}")
- # Locate the highest available platform
- file(GLOB android_platforms
- LIST_DIRECTORIES true
- RELATIVE "${ANDROID_SDK_ROOT}/platforms"
- "${ANDROID_SDK_ROOT}/platforms/*")
- # If list is not empty
- if(android_platforms)
- list(SORT android_platforms)
- list(REVERSE android_platforms)
- list(GET android_platforms 0 android_platform_latest)
+function(qt_internal_sort_android_platforms out_var)
+ if(CMAKE_VERSION GREATER_EQUAL 3.18)
+ set(platforms ${ARGN})
+ list(SORT platforms COMPARE NATURAL)
+ else()
+ # Simulate natural sorting:
+ # - prepend every platform with its version as three digits, zero-padded
+ # - regular sort
+ # - remove the padded version prefix
+ set(platforms)
+ foreach(platform IN LISTS ARGN)
+ set(version "000")
+ if(platform MATCHES ".*-([0-9]+)$")
+ set(version ${CMAKE_MATCH_1})
+ string(LENGTH "${version}" version_length)
+ math(EXPR padding_length "3 - ${version_length}")
+ string(REPEAT "0" ${padding_length} padding)
+ string(PREPEND version ${padding})
+ endif()
+ list(APPEND platforms "${version}~${platform}")
+ endforeach()
+ list(SORT platforms)
+ list(TRANSFORM platforms REPLACE "^.*~" "")
+ endif()
+ set("${out_var}" "${platforms}" PARENT_SCOPE)
+endfunction()
+
+macro(qt_internal_get_android_platform_version out_var android_platform)
+ string(REGEX REPLACE ".*-([0-9]+)$" "\\1" ${out_var} "${android_platform}")
+endmacro()
+
+# Locate the highest available platform
+file(GLOB android_platforms
+ LIST_DIRECTORIES true
+ RELATIVE "${ANDROID_SDK_ROOT}/platforms"
+ "${ANDROID_SDK_ROOT}/platforms/*")
+# If list is not empty
+if(android_platforms)
+ qt_internal_sort_android_platforms(android_platforms ${android_platforms})
+ list(REVERSE android_platforms)
+ list(GET android_platforms 0 android_platform_latest)
+
+ qt_internal_get_android_platform_version(latest_platform_version
+ "${android_platform_latest}")
+ qt_internal_get_android_platform_version(required_platform_version
+ "${QT_ANDROID_API_VERSION}")
+
+ if("${latest_platform_version}" VERSION_GREATER "${required_platform_version}")
set(QT_ANDROID_API_VERSION ${android_platform_latest})
- set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_VERSION}/android.jar")
endif()
endif()
+set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_VERSION}/android.jar")
if(NOT EXISTS "${QT_ANDROID_JAR}")
- message(FATAL_ERROR "No suitable Android SDK platform found. Minimum version is ${QT_ANDROID_API_VERSION}")
+ message(FATAL_ERROR
+ "No suitable Android SDK platform found in '${ANDROID_SDK_ROOT}/platforms'."
+ " Minimum version is ${QT_ANDROID_API_VERSION}"
+ )
endif()
message(STATUS "Using Android SDK API ${QT_ANDROID_API_VERSION} from ${ANDROID_SDK_ROOT}/platforms")
@@ -72,21 +106,6 @@ include(UseJava)
# Find JDK 8.0
find_package(Java 1.8 COMPONENTS Development REQUIRED)
-# Locate newest android sdk build tools
-if (NOT QT_ANDROID_SDK_BUILD_TOOLS_VERSION)
- file(GLOB android_build_tools
- LIST_DIRECTORIES true
- RELATIVE "${ANDROID_SDK_ROOT}/build-tools"
- "${ANDROID_SDK_ROOT}/build-tools/*")
- if (NOT android_build_tools)
- message(FATAL_ERROR "Could not locate Android SDK build tools under \"${ANDROID_SDK}/build-tools\"")
- endif()
- list(SORT android_build_tools)
- list(REVERSE android_build_tools)
- list(GET android_build_tools 0 android_build_tools_latest)
- set(QT_ANDROID_SDK_BUILD_TOOLS_VERSION ${android_build_tools_latest})
-endif()
-
# Ensure we are using the shared version of libc++
if(NOT ANDROID_STL STREQUAL c++_shared)
message(FATAL_ERROR "The Qt libraries on Android only supports the shared library configuration of stl. Please use -DANDROID_STL=\"c++_shared\" as configuration argument.")
@@ -142,231 +161,33 @@ define_property(TARGET
PROPERTY
QT_ANDROID_DEPLOYMENT_SETTINGS_FILE
BRIEF_DOCS
- " "
+ "This variable is used to specify the deployment settings JSON file for androiddeployqt."
FULL_DOCS
- " "
+ "This variable points to the path of the deployment settings JSON file, which holds properties required by androiddeployqt to package the Android app."
)
-# Generate deployment tool json
-function(qt_android_generate_deployment_settings target)
- # Information extracted from mkspecs/features/android/android_deployment_settings.prf
- if (NOT TARGET ${target})
- message(SEND_ERROR "${target} is not a cmake target")
- return()
- endif()
-
- get_target_property(target_type ${target} TYPE)
-
- if (NOT "${target_type}" STREQUAL "MODULE_LIBRARY")
- message(SEND_ERROR "QT_ANDROID_GENERATE_DEPLOYMENT_SETTINGS only works on Module targets")
- return()
- endif()
-
- get_target_property(target_source_dir ${target} SOURCE_DIR)
- get_target_property(target_binary_dir ${target} BINARY_DIR)
- get_target_property(target_output_name ${target} OUTPUT_NAME)
- if (NOT target_output_name)
- set(target_output_name ${target})
- endif()
- set(deploy_file "${target_binary_dir}/android-lib${target_output_name}.so-deployment-settings.json")
-
- set(file_contents "{\n")
- # content begin
- string(APPEND file_contents
- " \"description\": \"This file is generated by cmake to be read by androiddeployqt and should not be modified by hand.\",\n")
-
- # Host Qt Android install path
- if (NOT QT_BUILDING_QT)
- set(file_check "${Qt6_DIR}/plugins/platforms/android/libqtforandroid_${CMAKE_ANDROID_ARCH_ABI}.so")
- if (NOT EXISTS ${file_check})
- message(SEND_ERROR "Detected Qt installation does not contain libqtforandroid.so. This is most likely due to the installation not being a build of Qt for Android. Please update your settings.")
- return()
- endif()
- set(qt_android_install_dir ${Qt6_Dir})
- else()
- # Building from source, use the same install prefix
- set(qt_android_install_dir ${CMAKE_INSTALL_PREFIX})
- endif()
-
- file(TO_NATIVE_PATH "${qt_android_install_dir}" qt_android_install_dir_native)
- string(APPEND file_contents
- " \"qt\": \"${qt_android_install_dir_native}\",\n")
-
- # Android SDK path
- file(TO_NATIVE_PATH "${ANDROID_SDK_ROOT}" android_sdk_root_native)
- string(APPEND file_contents
- " \"sdk\": \"${android_sdk_root_native}\",\n")
-
- # Android SDK Build Tools Revision
- string(APPEND file_contents
- " \"sdkBuildToolsRevision\": \"${QT_ANDROID_SDK_BUILD_TOOLS_VERSION}\",\n")
-
- # Android NDK
- file(TO_NATIVE_PATH "${ANDROID_NDK}" android_ndk_root_native)
- string(APPEND file_contents
- " \"ndk\": \"${android_ndk_root_native}\",\n")
-
- # Setup LLVM toolchain
- string(APPEND file_contents
- " \"toolchain-prefix\": \"llvm\",\n")
- string(APPEND file_contents
- " \"tool-prefix\": \"llvm\",\n")
- string(APPEND file_contents
- " \"useLLVM\": true,\n")
-
- # NDK Toolchain Version
- string(APPEND file_contents
- " \"toolchain-version\": \"${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}\",\n")
-
- # NDK Host
- string(APPEND file_contents
- " \"ndk-host\": \"${ANDROID_NDK_HOST_SYSTEM_NAME}\",\n")
-
- if (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86")
- set(arch_value "i686-linux-android")
- elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
- set(arch_value "x86_64-linux-android")
- elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
- set(arch_value "aarch64-linux-android")
- else()
- set(arch_value "arm-linux-androideabi")
- endif()
-
- # Architecture
- string(APPEND file_contents
- " \"architectures\": { \"${CMAKE_ANDROID_ARCH_ABI}\" : \"${arch_value}\" },\n")
-
- # deployment dependencies
- get_target_property(android_deployment_dependencies
- ${target} QT_ANDROID_DEPLOYMENT_DEPENDENCIES)
- if (android_deployment_dependencies)
- list(JOIN android_deployment_dependencies "," android_deployment_dependencies)
- string(APPEND file_contents
- " \"deployment-dependencies\": \"${android_deployment_dependencies}\",\n")
- endif()
-
- # Extra plugins
- get_target_property(android_extra_plugins
- ${target} QT_ANDROID_EXTRA_PLUGINS)
- if (android_extra_plugins)
- list(JOIN android_extra_plugins "," android_extra_plugins)
- string(APPEND file_contents
- " \"android-extra-plugins\": \"${android_extra_plugins}\",\n")
- endif()
-
- # Extra libs
- get_target_property(android_extra_libs
- ${target} QT_ANDROID_EXTRA_LIBS)
- if (android_extra_libs)
- list(JOIN android_extra_libs "," android_extra_libs)
- string(APPEND file_contents
- " \"android-extra-libs\": \"${android_extra_libs}\",\n")
- endif()
-
- # package source dir
- get_target_property(android_package_source_dir
- ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
- if (android_package_source_dir)
- file(TO_NATIVE_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()
-
- #TODO: ANDROID_VERSION_NAME, doesn't seem to be used?
-
- #TODO: ANDROID_VERSION_CODE, doesn't seem to be used?
-
- get_target_property(qml_import_path ${target} QT_QML_IMPORT_PATH)
- if (qml_import_path)
- file(TO_NATIVE_PATH "${qml_import_path}" qml_import_path_native)
- string(APPEND file_contents
- " \"qml-import-path\": \"${qml_import_path_native}\",\n")
- endif()
-
- get_target_property(qml_root_path ${target} QT_QML_ROOT_PATH)
- if(NOT qml_root_path)
- set(qml_root_path "${target_source_dir}")
- endif()
- file(TO_NATIVE_PATH "${qml_root_path}" qml_root_path_native)
- string(APPEND file_contents
- " \"qml-root-path\": \"${qml_root_path_native}\",\n")
-
- # App binary
- string(APPEND file_contents
- " \"application-binary\": \"${target_output_name}\",\n")
-
- # App command-line arguments
- string(APPEND file_contents
- " \"android-application-arguments\": \"${QT_ANDROID_APPLICATION_ARGUMENTS}\",\n")
-
- # Override qmlimportscanner binary path
- set(qml_importscanner_binary_path "${QT_HOST_PATH}/bin/qmlimportscanner")
- if (WIN32)
- string(APPEND qml_importscanner_binary_path ".exe")
- endif()
- file(TO_NATIVE_PATH "${qml_importscanner_binary_path}" qml_importscanner_binary_path_native)
- string(APPEND file_contents
- " \"qml-importscanner-binary\" : \"${qml_importscanner_binary_path_native}\",\n")
-
- # Last item in json file
-
- # base location of stdlibc++, will be suffixed by androiddeploy qt
- set(android_ndk_stdlib_base_path
- "${ANDROID_NDK}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/"
- )
- string(APPEND file_contents
- " \"stdcpp-path\": \"${android_ndk_stdlib_base_path}\"\n")
-
- # content end
- string(APPEND file_contents "}\n")
-
- file(WRITE ${deploy_file} ${file_contents})
-
- set_target_properties(${target}
- PROPERTIES
- QT_ANDROID_DEPLOYMENT_SETTINGS_FILE ${deploy_file}
- )
-endfunction()
-
-function(qt_android_apply_arch_suffix target)
- get_target_property(target_type ${target} TYPE)
- if (target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
- set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.so")
- elseif (target_type STREQUAL "STATIC_LIBRARY")
- set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.a")
- endif()
-endfunction()
-
-# Add custom target to package the APK
-function(qt_android_add_apk_target target)
- get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
- if (NOT deployment_file)
- message(FATAL_ERROR "Target ${target} is not a valid android executable target\n")
- endif()
-
- set(deployment_tool "${QT_HOST_PATH}/bin/androiddeployqt")
- set(apk_dir "$<TARGET_PROPERTY:${target},BINARY_DIR>/android-build")
- add_custom_target(${target}_prepare_apk_dir
- DEPENDS ${target}
- COMMAND ${CMAKE_COMMAND}
- -E copy $<TARGET_FILE:${target}>
- "${apk_dir}/libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>"
- COMMENT "Copying ${target} binarty to apk folder"
- )
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_SYSTEM_LIBS_PREFIX
+ BRIEF_DOCS
+ "This variable is used to specify a path to Qt libraries on the target device in Android."
+ FULL_DOCS
+ "This variable can be used to provide a custom system library path to use for library loading lookup on Android. This is necessary when using Qt libraries installed outside an app's default native (JNI) library directory."
+)
- add_custom_target(${target}_make_apk
- DEPENDS ${target}_prepare_apk_dir
- COMMAND ${deployment_tool}
- --input ${deployment_file}
- --output ${apk_dir}
- COMMENT "Creating APK for ${target}"
- )
-endfunction()
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_NO_DEPLOY_QT_LIBS
+ BRIEF_DOCS
+ "This variable is used to control whether Qt libraries should be deployed inside the APK on Android."
+ FULL_DOCS
+ "This variable can be used to exclude Qt shared libraries from being packaged inside the APK when deploying on Android. Not supported when deploying as Android Application Bundle."
+)
-# Add a test for Android which will be run by the android test runner tool
-function(qt_android_add_test target)
- set(deployment_tool "${QT_HOST_PATH}/bin/androiddeployqt")
- set(test_runner "${QT_HOST_PATH}/bin/androidtestrunner")
+# Returns test execution arguments for Android targets
+function(qt_internal_android_test_arguments target timeout out_test_runner out_test_arguments)
+ set(${out_test_runner} "${QT_HOST_PATH}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}/androidtestrunner" PARENT_SCOPE)
+ set(deployment_tool "${QT_HOST_PATH}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}/androiddeployqt")
get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
if (NOT deployment_file)
@@ -374,16 +195,20 @@ function(qt_android_add_test target)
endif()
set(target_binary_dir "$<TARGET_PROPERTY:${target},BINARY_DIR>")
- set(apk_dir "${target_binary_dir}/android-build")
-
- add_test(NAME "${target}"
- COMMAND "${test_runner}"
- --androiddeployqt "${deployment_tool} --input ${deployment_file}"
- --adb "${ANDROID_SDK_ROOT}/platform-tools/adb"
- --path "${apk_dir}"
- --skip-install-root
- --make "${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
- --apk "${apk_dir}/${target}.apk"
- --verbose
+ if(QT_USE_TARGET_ANDROID_BUILD_DIR)
+ set(apk_dir "${target_binary_dir}/android-build-${target}")
+ else()
+ set(apk_dir "${target_binary_dir}/android-build")
+ endif()
+ set(${out_test_arguments}
+ "--path" "${apk_dir}"
+ "--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb"
+ "--skip-install-root"
+ "--make" "\"${CMAKE_COMMAND}\" --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
+ "--apk" "${apk_dir}/${target}.apk"
+ "--ndk-stack" "${ANDROID_NDK_ROOT}/ndk-stack"
+ "--timeout" "${timeout}"
+ "--verbose"
+ PARENT_SCOPE
)
endfunction()