Warning, /frameworks/extra-cmake-modules/modules/ECMAddAndroidApk.cmake is written in an unsupported language. File is not indexed.
0001 # SPDX-FileCopyrightText: 2018-2023 Aleix Pol <aleixpol@kde.org>
0002 # SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
0003 # SPDX-License-Identifier: BSD-2-Clause
0004
0005 #[=======================================================================[.rst:
0006 ECMAddAndroidApk
0007 ----------------
0008
0009 Functions for creating Android APK packages using Qt6's ``androiddeployqt`` tool
0010 as well as the associated Fastlane metadata.
0011
0012 ::
0013
0014 ecm_add_android_apk(<target>
0015 [ANDROID_DIR <dir>]
0016 # TODO extra args?
0017 )
0018
0019 Creates an Android APK for the given target.
0020
0021 If ``ANDROID_DIR`` is given, the Android manifest file as well as any potential
0022 Gradle build system files or Java/Kotlin source files are taken from that directory.
0023 If not set, the standard template shipped with Qt6 is used, which in usually not
0024 what you want for production applications.
0025
0026 The use of this function creates a build target called ``create-apk-<target>``
0027 which will run ``androiddeployqt`` to produce an (unsigned) APK, as well
0028 as convert Appstream application metadata (if present) into the Fastlane format used
0029 by F-Droid and Play store automation.
0030
0031 There's also a ``create-apk`` convenience target being created that
0032 will build all APKs defined in a project.
0033
0034 When building for another platform than Android, this function does nothing.
0035
0036 The following variables impact the behavior:
0037 ``ECM_ADDITIONAL_FIND_ROOT_PATH``
0038 See documentation in the Android toolchain file.
0039
0040 ``ECM_APK_STAGING_ROOT_PATH``
0041 For use with Craft's image directory. If set this is used as the source
0042 for all content of the APK rather than the search paths used for building.
0043 This allows to separate e.g. development files from what ends up in the APK.
0044
0045 Since 6.0.0
0046 #]=======================================================================]
0047
0048 # make ExecuteCoreModules test pass on Qt5
0049 include(${CMAKE_CURRENT_LIST_DIR}/../modules/QtVersionOption.cmake)
0050 if (QT_MAJOR_VERSION EQUAL 5)
0051 message(WARNING "ECMAddAndroidApk is not compatible with Qt5 - skipping.")
0052 return()
0053 endif()
0054
0055 find_package(Qt6Core REQUIRED) # required for the following to work stand-alone
0056 find_package(Qt6CoreTools REQUIRED)
0057 find_package(Python3 COMPONENTS Interpreter REQUIRED)
0058
0059 set(_ECM_TOOLCHAIN_DIR "${CMAKE_CURRENT_LIST_DIR}/../toolchain")
0060
0061 function (ecm_add_android_apk TARGET)
0062 cmake_parse_arguments(ARGS "" "ANDROID_DIR" "" ${ARGN})
0063 if (NOT ANDROID)
0064 return()
0065 endif()
0066
0067 set(APK_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${TARGET}_build_apk/")
0068 set(APK_EXECUTABLE_PATH "${APK_OUTPUT_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/lib${TARGET}_${CMAKE_ANDROID_ARCH_ABI}.so")
0069
0070 set(QML_IMPORT_PATHS "")
0071 # add build directory to the search path as well, so this works without installation
0072 if (EXISTS ${CMAKE_BINARY_DIR}/lib)
0073 set(QML_IMPORT_PATHS ${CMAKE_BINARY_DIR}/lib)
0074 endif()
0075 if (ECM_APK_STAGING_ROOT_PATH)
0076 set(QML_IMPORT_PATHS "${ECM_APK_STAGING_ROOT_PATH}/lib/qml")
0077 set(ANDROID_QT6_INSTALL_PREFIX ${ECM_APK_STAGING_ROOT_PATH})
0078 else()
0079 foreach(prefix ${ECM_ADDITIONAL_FIND_ROOT_PATH})
0080 # qmlimportscanner chokes on symlinks, so we need to resolve those first
0081 get_filename_component(qml_path "${prefix}/lib/qml" REALPATH)
0082 if(EXISTS ${qml_path})
0083 if (QML_IMPORT_PATHS)
0084 set(QML_IMPORT_PATHS "${QML_IMPORT_PATHS},${qml_path}")
0085 else()
0086 set(QML_IMPORT_PATHS "${qml_path}")
0087 endif()
0088 endif()
0089 endforeach()
0090 set(ANDROID_QT6_INSTALL_PREFIX ${QT6_INSTALL_PREFIX})
0091 endif()
0092 if (QML_IMPORT_PATHS)
0093 set(DEFINE_QML_IMPORT_PATHS "\"qml-import-paths\": \"${QML_IMPORT_PATHS}\",")
0094 endif()
0095
0096 set(EXTRA_PREFIX_DIRS "\"${CMAKE_BINARY_DIR}\"")
0097 set(EXTRA_LIB_DIRS "\"${CMAKE_BINARY_DIR}/lib\"")
0098 if (ECM_APK_STAGING_ROOT_PATH)
0099 set(EXTRA_PREFIX_DIRS "${EXTRA_PREFIX_DIRS}, \"${ECM_APK_STAGING_ROOT_PATH}\"")
0100 set(EXTRA_LIB_DIRS "${EXTRA_LIB_DIRS}, \"${ECM_APK_STAGING_ROOT_PATH}/lib\"")
0101 else()
0102 foreach(prefix ${ECM_ADDITIONAL_FIND_ROOT_PATH})
0103 set(EXTRA_PREFIX_DIRS "${EXTRA_PREFIX_DIRS}, \"${prefix}\"")
0104 set(EXTRA_LIB_DIRS "${EXTRA_LIB_DIRS}, \"${prefix}/lib\"")
0105 endforeach()
0106 endif()
0107
0108 if (ARGS_ANDROID_DIR AND EXISTS ${ARGS_ANDROID_DIR}/AndroidManifest.xml)
0109 set(ANDROID_APK_DIR ${ARGS_ANDROID_DIR})
0110 else()
0111 message("Using default Qt APK template - this is often not intentional!")
0112 get_filename_component(_qtCore_install_prefix "${Qt6Core_DIR}/../../../" ABSOLUTE)
0113 set(ANDROID_APK_DIR "${_qtCore_install_prefix}/src/android/templates/")
0114 endif()
0115
0116 get_target_property(QT6_RCC_BINARY Qt6::rcc LOCATION)
0117 string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" _LOWER_CMAKE_HOST_SYSTEM_NAME)
0118 configure_file("${_ECM_TOOLCHAIN_DIR}/deployment-file-qt6.json.in" "${CMAKE_BINARY_DIR}/${TARGET}-deployment.json.in")
0119
0120 if (NOT TARGET create-apk)
0121 add_custom_target(create-apk)
0122 if (NOT DEFINED ANDROID_FASTLANE_METADATA_OUTPUT_DIR)
0123 set(ANDROID_FASTLANE_METADATA_OUTPUT_DIR ${CMAKE_BINARY_DIR}/fastlane)
0124 endif()
0125 add_custom_target(create-fastlane
0126 COMMAND Python3::Interpreter ${_ECM_TOOLCHAIN_DIR}/generate-fastlane-metadata.py --output ${ANDROID_FASTLANE_METADATA_OUTPUT_DIR} --source ${CMAKE_SOURCE_DIR}
0127 )
0128 endif()
0129
0130 if (NOT DEFINED ANDROID_APK_OUTPUT_DIR)
0131 set(ANDROID_APK_OUTPUT_DIR ${APK_OUTPUT_DIR})
0132 endif()
0133
0134 if (CMAKE_GENERATOR STREQUAL "Unix Makefiles")
0135 set(arguments "\\$(ARGS)")
0136 endif()
0137
0138 if (NOT ECM_APK_STAGING_ROOT_PATH)
0139 set(ECM_APK_STAGING_ROOT_PATH "${CMAKE_INSTALL_PREFIX}")
0140 endif()
0141
0142 file(WRITE ${CMAKE_BINARY_DIR}/ranlib "${CMAKE_RANLIB}")
0143 set(CREATEAPK_TARGET_NAME "create-apk-${TARGET}")
0144 add_custom_target(${CREATEAPK_TARGET_NAME}
0145 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
0146 COMMAND ${CMAKE_COMMAND} -E echo "Generating $<TARGET_NAME:${TARGET}> with $<TARGET_FILE:Qt6::androiddeployqt>"
0147 COMMAND ${CMAKE_COMMAND} -E remove_directory "${APK_OUTPUT_DIR}"
0148 COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${TARGET}>" "${APK_EXECUTABLE_PATH}"
0149 COMMAND LANG=C ${CMAKE_COMMAND} "-DTARGET=$<TARGET_FILE:${TARGET}>" -P ${_ECM_TOOLCHAIN_DIR}/hasMainSymbol.cmake
0150 COMMAND LANG=C ${CMAKE_COMMAND}
0151 -DINPUT_FILE="${CMAKE_BINARY_DIR}/${TARGET}-deployment.json.in"
0152 -DOUTPUT_FILE="${CMAKE_BINARY_DIR}/${TARGET}-deployment.json"
0153 "-DTARGET=$<TARGET_FILE:${TARGET}>"
0154 "-DOUTPUT_DIR=$<TARGET_FILE_DIR:${TARGET}>"
0155 "-DEXPORT_DIR=${ECM_APK_STAGING_ROOT_PATH}"
0156 "-DECM_ADDITIONAL_FIND_ROOT_PATH=\"${ECM_ADDITIONAL_FIND_ROOT_PATH}\""
0157 -P ${_ECM_TOOLCHAIN_DIR}/specifydependencies.cmake
0158 COMMAND Qt6::androiddeployqt
0159 ${ANDROIDDEPLOYQT_EXTRA_ARGS}
0160 --gradle
0161 --input "${CMAKE_BINARY_DIR}/${TARGET}-deployment.json"
0162 --apk "${ANDROID_APK_OUTPUT_DIR}/${TARGET}-${CMAKE_ANDROID_ARCH_ABI}.apk"
0163 --output "${APK_OUTPUT_DIR}"
0164 --android-platform android-${ANDROID_SDK_COMPILE_API}
0165 --deployment bundled
0166 --qml-importscanner-binary $<TARGET_FILE:Qt6::qmlimportscanner>
0167 ${arguments}
0168 )
0169
0170 add_dependencies(create-apk ${CREATEAPK_TARGET_NAME})
0171 add_dependencies(${CREATEAPK_TARGET_NAME} create-fastlane)
0172 endfunction()