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()