#.rst: # AndroidToolchain # ---------------- # # Enable easy compilation of cmake projects on Android. # # By using this android toolchain, the projects will be set up to compile the # specified project targeting an Android platform, depending on its input. # Furthermore, if desired, an APK can be directly generated by using the # `androiddeployqt `_ tool. # # CMake upstream has Android support now. This module will still give us some # useful features offering androiddeployqt integration and adequate executables # format for our Android applications. # # Since we are using CMake Android support, any information from CMake documentation # still applies: # https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html#cross-compiling-for-android # # .. note:: # # This module requires CMake 3.7. # # Since 1.7.0. # # Usage # ===== # # To use this file, you need to set the ``CMAKE_TOOLCHAIN_FILE`` to point to # ``Android.cmake`` on the command line:: # # cmake -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake # # You will also need to provide the locations of the Android NDK and SDK. This # can be done on the commandline or with environment variables; in either case # the variable names are: # # ``CMAKE_ANDROID_NDK`` # The NDK root path. # ``ANDROID_SDK_ROOT`` # The SDK root path. # # Additional options are specified as cache variables (eg: on the command line): # # ``ANDROID_ABI`` # The ABI to use. See the ``sources/cxx-stl/gnu-libstdc++/*/libs`` # directories in the NDK. Default: ``armeabi-v7a``. # ``ANDROID_SDK_BUILD_TOOLS_REVISION`` # The build tools version to use. Default: ``21.1.1``. # ``ANDROID_EXTRA_LIBS`` # The ";"-separated list of full paths to libs to include in resulting APK. # # For integrating other libraries which are not part of the Android toolchain, # like Qt5, and installed to a separate prefix on the host system, the install # prefixes of those libraries would be passed as alternative roots as list via # ``ECM_ADDITIONAL_FIND_ROOT_PATH``. Since 5.30.0. # # For example, for integrating a Qt5 for Android present at # ``~/Qt/5.14.2/android/`` and some other libraries installed to # the prefix ``/opt/android/foo``, you would use:: # # cmake \ # -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \ # -DECM_ADDITIONAL_FIND_ROOT_PATH="~/Qt/5.14.2/android/;/opt/android/foo" # # If your project uses ``find_package()`` to locate build tools on the host # system, make sure to pass ``CMAKE_FIND_ROOT_PATH_BOTH`` or # ``NO_CMAKE_FIND_ROOT_PATH`` as argument in the call. See the # ``find_package()`` documentation for more details. # # Deploying Qt Applications # ========================= # # After building the application, you will need to generate an APK that can be # deployed to an Android device. This module integrates androiddeployqt support # to help with this for Qt-based projects. To enable this, set the # ``QTANDROID_EXPORTED_TARGET`` variable to the targets you wish to export as an # APK (in a ;-separed list), as well as ``ANDROID_APK_DIR`` to a directory # containing some basic information. This will create a ``create-apk-`` # target that will generate the APK file. See the `Qt on Android deployment # documentation `_ for more # information. # # For example, you could do:: # # cmake \ # -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \ # -DQTANDROID_EXPORTED_TARGET=myapp \ # -DANDROID_APK_DIR=myapp-apk # make # make create-apk-myapp # # You can specify the APK output directory by setting ``ANDROID_APK_OUTPUT_DIR``. # Otherwise the APK can be found in ``myapp_build_apk/`` in the build directory. # # The create-apk-myapp target will be able to take an ARGS parameter with further # arguments for androiddeployqt. For example, one can use:: # # make create-apk-myapp ARGS="--install" # # To install the apk to test. To generate a signed apk, one can do it with the # following syntax:: # # make create-apk-myapp ARGS="--sign ~/my.keystore alias_name" # # In case it's needed for your application to set the APK directory from cmake # scripting you can also set the directory as the ANDROID_APK_DIR property of # the create-apk-myapp target. # # See Android documentation on how to create a keystore to use # ============================================================================= # SPDX-FileCopyrightText: 2014 Aleix Pol i Gonzalez # # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION "3.7") macro(set_deprecated_variable actual_variable deprecated_variable default_value) set(${deprecated_variable} "${default_value}" CACHE STRING "Deprecated. Use ${actual_variable}") if (NOT DEFINED ${actual_variable}) set(${actual_variable} ${${deprecated_variable}}) endif() endmacro() set_deprecated_variable(CMAKE_ANDROID_NDK ANDROID_NDK "$ENV{ANDROID_NDK}") set_deprecated_variable(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION ANDROID_GCC_VERSION "clang") set_deprecated_variable(CMAKE_ANDROID_API ANDROID_API_LEVEL "21") if(NOT DEFINED ENV{ANDROID_ARCH}) set(ENV{ANDROID_ARCH} "arm") endif() set_deprecated_variable(CMAKE_ANDROID_ARCH ANDROID_ARCHITECTURE $ENV{ANDROID_ARCH}) if(NOT DEFINED ENV{ANDROID_ARCH_ABI}) set(ENV{ANDROID_ARCH_ABI} "armeabi-v7a") endif() set_deprecated_variable(CMAKE_ANDROID_ARCH_ABI ANDROID_ABI "$ENV{ANDROID_ARCH_ABI}") set(ANDROID_SDK_ROOT "$ENV{ANDROID_SDK_ROOT}" CACHE PATH "Android SDK path") file(GLOB build-tools LIST_DIRECTORIES TRUE RELATIVE ${ANDROID_SDK_ROOT}/build-tools ${ANDROID_SDK_ROOT}/build-tools/*) list(GET build-tools 0 _default_sdk) set(ANDROID_SDK_BUILD_TOOLS_REVISION "${_default_sdk}" CACHE STRING "Android API Level") set(CMAKE_SYSTEM_VERSION ${CMAKE_ANDROID_API}) set(CMAKE_SYSTEM_NAME Android) if (NOT CMAKE_ANDROID_STL_TYPE) set(CMAKE_ANDROID_STL_TYPE c++_shared) endif() # let the Android NDK toolchain file do the actual work set(ANDROID_PLATFORM "android-${CMAKE_ANDROID_API}") set(ANDROID_STL ${CMAKE_ANDROID_STL_TYPE}) include(${CMAKE_ANDROID_NDK}/build/cmake/android.toolchain.cmake REQUIRED) # these aren't set yet at this point by the Android toolchain, but without # those the find_package() call in ECMAndroidDeployQt will fail set(CMAKE_FIND_LIBRARY_PREFIXES "lib") set(CMAKE_FIND_LIBRARY_SUFFIXES "_${CMAKE_ANDROID_ARCH_ABI}.so" ".so" ".a") # Work around Qt messing with CMAKE_SHARED_LIBRARY_SUFFIX and thus breaking find_library() # Unfortunately, just setting CMAKE_FIND_LIBRARY_SUFFIXES here won't help, as this will # be subsequently overwritten. macro(addAbiSuffix _var _access) if (${_access} STREQUAL "MODIFIED_ACCESS") list(PREPEND CMAKE_FIND_LIBRARY_SUFFIXES "_${CMAKE_ANDROID_ARCH_ABI}.so") endif() endmacro() variable_watch(CMAKE_FIND_LIBRARY_SUFFIXES addAbiSuffix) # determine STL architecture, which is using a different format than ANDROID_ARCH_ABI string(REGEX REPLACE "-(clang)?([0-9].[0-9])?$" "" ECM_ANDROID_STL_ARCH ${ANDROID_TOOLCHAIN_NAME}) if (NOT DEFINED ECM_ADDITIONAL_FIND_ROOT_PATH) SET(ECM_ADDITIONAL_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH}) endif() LIST(APPEND CMAKE_FIND_ROOT_PATH ${ECM_ADDITIONAL_FIND_ROOT_PATH}) #we want executables to be shared libraries, hooks will invoke the exported cmake function set(CMAKE_CXX_LINK_EXECUTABLE " -o " ) set(ECM_DIR "${CMAKE_CURRENT_LIST_DIR}/../cmake" CACHE STRING "") ######### generation # Need to ensure we only get in here once, as this file is included twice: # from CMakeDetermineSystem.cmake and from CMakeSystem.cmake generated within the # build directory. if(DEFINED QTANDROID_EXPORTED_TARGET AND NOT TARGET "create-apk") get_filename_component(_CMAKE_ANDROID_DIR "${CMAKE_TOOLCHAIN_FILE}" PATH) list(LENGTH QTANDROID_EXPORTED_TARGET targetsCount) include(${_CMAKE_ANDROID_DIR}/ECMAndroidDeployQt.cmake) math(EXPR last "${targetsCount}-1") foreach(idx RANGE 0 ${last}) list(GET QTANDROID_EXPORTED_TARGET ${idx} exportedTarget) list(GET ANDROID_APK_DIR ${idx} APK_DIR) if(APK_DIR AND NOT EXISTS "${ANDROID_APK_DIR}/AndroidManifest.xml" AND IS_ABSOLUTE ANDROID_APK_DIR) message(FATAL_ERROR "Cannot find ${APK_DIR}/AndroidManifest.xml according to ANDROID_APK_DIR. ${ANDROID_APK_DIR} ${exportedTarget}") elseif(NOT APK_DIR) get_filename_component(_qt5Core_install_prefix "${Qt5Core_DIR}/../../../" ABSOLUTE) set(APK_DIR "${_qt5Core_install_prefix}/src/android/templates/") endif() ecm_androiddeployqt("${exportedTarget}" "${ECM_ADDITIONAL_FIND_ROOT_PATH}") set_target_properties(create-apk-${exportedTarget} PROPERTIES ANDROID_APK_DIR "${APK_DIR}") endforeach() else() message(STATUS "You can export a target by specifying -DQTANDROID_EXPORTED_TARGET= and -DANDROID_APK_DIR=") endif()