Warning, /multimedia/kid3/android/qt-android-cmake/AddQtAndroidApk.cmake is written in an unsupported language. File is not indexed.

0001 cmake_minimum_required(VERSION 3.0)
0002 cmake_policy(SET CMP0026 OLD) # allow use of the LOCATION target property
0003 
0004 # store the current source directory for future use
0005 set(QT_ANDROID_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
0006 
0007 # check the JAVA_HOME environment variable
0008 if(JAVA_HOME)
0009     # Set JAVA_HOME environment variable.
0010     set(ENV{JAVA_HOME} ${JAVA_HOME})
0011 else()
0012     set(JAVA_HOME $ENV{JAVA_HOME})
0013     if(NOT JAVA_HOME)
0014         message(FATAL_ERROR "The JAVA_HOME environment variable is not set. Please set it or the JAVA_HOME CMake variable to the root directory of the JDK.")
0015     endif()
0016 endif()
0017 
0018 # make sure that the Android toolchain is used
0019 if(NOT ANDROID)
0020     message(FATAL_ERROR "Trying to use the CMake Android package without the Android toolchain. Please use the provided toolchain (toolchain/android.toolchain.cmake)")
0021 endif()
0022 
0023 # find the Qt root directory
0024 if(NOT Qt${QT_VERSION_MAJOR}Core_DIR)
0025     find_package(Qt${QT_VERSION_MAJOR}Core REQUIRED)
0026 endif()
0027 get_filename_component(QT_ANDROID_QT_ROOT "${Qt${QT_VERSION_MAJOR}Core_DIR}/../../.." ABSOLUTE)
0028 message(STATUS "Found Qt for Android: ${QT_ANDROID_QT_ROOT}")
0029 
0030 # find the Android SDK
0031 if(NOT QT_ANDROID_SDK_ROOT)
0032     set(QT_ANDROID_SDK_ROOT $ENV{ANDROID_SDK})
0033     if(NOT QT_ANDROID_SDK_ROOT)
0034         message(FATAL_ERROR "Could not find the Android SDK. Please set either the ANDROID_SDK environment variable, or the QT_ANDROID_SDK_ROOT CMake variable to the root directory of the Android SDK")
0035     endif()
0036 endif()
0037 string(REPLACE "\\" "/" QT_ANDROID_SDK_ROOT ${QT_ANDROID_SDK_ROOT}) # androiddeployqt doesn't like backslashes in paths
0038 message(STATUS "Found Android SDK: ${QT_ANDROID_SDK_ROOT}")
0039 
0040 # find the Android NDK
0041 if(NOT QT_ANDROID_NDK_ROOT)
0042     set(QT_ANDROID_NDK_ROOT $ENV{ANDROID_NDK})
0043     if(NOT QT_ANDROID_NDK_ROOT)
0044         set(QT_ANDROID_NDK_ROOT ${ANDROID_NDK})
0045         if(NOT QT_ANDROID_NDK_ROOT)
0046         message(FATAL_ERROR "Could not find the Android NDK. Please set either the ANDROID_NDK environment or CMake variable, or the QT_ANDROID_NDK_ROOT CMake variable to the root directory of the Android NDK")
0047         endif()
0048     endif()
0049 endif()
0050 string(REPLACE "\\" "/" QT_ANDROID_NDK_ROOT ${QT_ANDROID_NDK_ROOT}) # androiddeployqt doesn't like backslashes in paths
0051 message(STATUS "Found Android NDK: ${QT_ANDROID_NDK_ROOT}")
0052 
0053 option(APK_ALL_TARGET "generate apk package with target 'all'" ON)
0054 if(APK_ALL_TARGET)
0055     SET(APK_ALL ALL)
0056 endif()
0057 
0058 include(CMakeParseArguments)
0059 
0060 # define a macro to create an Android APK target
0061 #
0062 # example:
0063 # add_qt_android_apk(my_app_apk my_app
0064 #     NAME "My App"
0065 #     VERSION_CODE 12
0066 #     PACKAGE_NAME "org.mycompany.myapp"
0067 #     PACKAGE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/my-android-sources
0068 #     KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/mykey.keystore myalias
0069 #     KEYSTORE_PASSWORD xxxx
0070 #     DEPENDS a_linked_target "path/to/a_linked_library.so" ...
0071 #     INSTALL
0072 #)
0073 #
0074 macro(add_qt_android_apk TARGET SOURCE_TARGET)
0075 
0076     # parse the macro arguments
0077     cmake_parse_arguments(ARG "INSTALL" "NAME;VERSION_CODE;PACKAGE_NAME;PACKAGE_SOURCES;KEYSTORE_PASSWORD" "DEPENDS;KEYSTORE;DEPLOYMENT_DEPENDS" ${ARGN})
0078 
0079     # extract the full path of the source target binary
0080     if(CMAKE_BUILD_TYPE STREQUAL "Debug")
0081         get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY DEBUG_LOCATION)
0082     else()
0083         get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY LOCATION)
0084     endif()
0085 
0086     # define the application name
0087     if(ARG_NAME)
0088         set(QT_ANDROID_APP_NAME ${ARG_NAME})
0089     else()
0090         set(QT_ANDROID_APP_NAME ${SOURCE_TARGET})
0091     endif()
0092 
0093     # define the application package name
0094     if(ARG_PACKAGE_NAME)
0095         set(QT_ANDROID_APP_PACKAGE_NAME ${ARG_PACKAGE_NAME})
0096     else()
0097         set(QT_ANDROID_APP_PACKAGE_NAME org.qtproject.${SOURCE_TARGET})
0098     endif()
0099 
0100     # set sdkBuildToolsRevision in qtdeploy.json
0101     if(QT_ANDROID_BUILD_TOOLS_REVISION)
0102         set(QT_ANDROID_SDK_BUILDTOOLS_REVISION ${QT_ANDROID_BUILD_TOOLS_REVISION})
0103     else()
0104         # detect latest Android SDK build-tools revision
0105         set(QT_ANDROID_SDK_BUILDTOOLS_REVISION "0.0.0")
0106         file(GLOB ALL_BUILD_TOOLS_VERSIONS RELATIVE ${QT_ANDROID_SDK_ROOT}/build-tools ${QT_ANDROID_SDK_ROOT}/build-tools/*)
0107         foreach(BUILD_TOOLS_VERSION ${ALL_BUILD_TOOLS_VERSIONS})
0108             # find subfolder with greatest version
0109             if (${BUILD_TOOLS_VERSION} VERSION_GREATER ${QT_ANDROID_SDK_BUILDTOOLS_REVISION})
0110                 set(QT_ANDROID_SDK_BUILDTOOLS_REVISION ${BUILD_TOOLS_VERSION})
0111             endif()
0112         endforeach()
0113         message("Detected Android SDK build tools version ${QT_ANDROID_SDK_BUILDTOOLS_REVISION}")
0114     endif()
0115 
0116     # define the application source package directory
0117     if(ARG_PACKAGE_SOURCES)
0118         set(QT_ANDROID_APP_PACKAGE_SOURCE_ROOT ${ARG_PACKAGE_SOURCES})
0119     else()
0120         # get version code from arguments, or generate a fixed one if not provided
0121         if(NOT QT_ANDROID_APP_VERSION_CODE)
0122             set(QT_ANDROID_APP_VERSION_CODE ${ARG_VERSION_CODE})
0123         endif()
0124         if(NOT QT_ANDROID_APP_VERSION_CODE)
0125             set(QT_ANDROID_APP_VERSION_CODE 1)
0126         endif()
0127 
0128         # try to extract the app version from the target properties, or use the version code if not provided
0129         get_property(QT_ANDROID_APP_VERSION TARGET ${SOURCE_TARGET} PROPERTY VERSION)
0130         if(NOT QT_ANDROID_APP_VERSION)
0131             set(QT_ANDROID_APP_VERSION ${QT_ANDROID_APP_VERSION_CODE})
0132         endif()
0133 
0134         # create a subdirectory for the extra package sources
0135         set(QT_ANDROID_APP_PACKAGE_SOURCE_ROOT "${CMAKE_CURRENT_BINARY_DIR}/package")
0136 
0137         # generate a manifest from the template
0138         configure_file(${QT_ANDROID_SOURCE_DIR}/AndroidManifest.xml.in ${QT_ANDROID_APP_PACKAGE_SOURCE_ROOT}/AndroidManifest.xml @ONLY)
0139     endif()
0140 
0141     # define the STL shared library path
0142     if(ANDROID_STL_SHARED_LIBRARIES)
0143         list(GET ANDROID_STL_SHARED_LIBRARIES 0 STL_LIBRARY_NAME) # we can only give one to androiddeployqt
0144         if(ANDROID_STL_PATH)
0145             set(QT_ANDROID_STL_PATH "${ANDROID_STL_PATH}/libs/${ANDROID_ABI}/lib${STL_LIBRARY_NAME}.so")
0146         else()
0147             set(QT_ANDROID_STL_PATH "${ANDROID_NDK}/sources/cxx-stl/${ANDROID_STL_PREFIX}/libs/${ANDROID_ABI}/lib${STL_LIBRARY_NAME}.so")
0148         endif()
0149     else()
0150         set(QT_ANDROID_STL_PATH "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/libs/${ANDROID_ABI}/libgnustl_shared.so")
0151         if(NOT EXISTS "${QT_ANDROID_STL_PATH}")
0152             set(QT_ANDROID_STL_PATH "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libc++_shared.so")
0153         endif()
0154         if(NOT EXISTS "${QT_ANDROID_STL_PATH}")
0155             set(QT_ANDROID_STL_PATH)
0156         endif()
0157     endif()
0158 
0159     # set the list of dependent libraries
0160     if(ARG_DEPENDS)
0161         foreach(LIB ${ARG_DEPENDS})
0162             if(TARGET ${LIB})
0163                 # item is a CMake target, extract the library path
0164                 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
0165                     get_property(LIB_PATH TARGET ${LIB} PROPERTY DEBUG_LOCATION)
0166                 else()
0167                     get_property(LIB_PATH TARGET ${LIB} PROPERTY LOCATION)
0168                 endif()
0169                 set(LIB ${LIB_PATH})
0170             endif()
0171         if(EXTRA_LIBS)
0172             set(EXTRA_LIBS "${EXTRA_LIBS},${LIB}")
0173         else()
0174             set(EXTRA_LIBS "${LIB}")
0175         endif()
0176         endforeach()
0177         set(QT_ANDROID_APP_EXTRA_LIBS "\"android-extra-libs\": \"${EXTRA_LIBS}\",")
0178     endif()
0179 
0180     # set some toolchain variables used by androiddeployqt;
0181     # unfortunately, Qt tries to build paths from these variables although these full paths
0182     # are already available in the toochain file, so we have to parse them
0183     string(REGEX MATCH "${ANDROID_NDK}/toolchains/(.*)-(.*)/prebuilt/.*" ANDROID_TOOLCHAIN_PARSED ${ANDROID_TOOLCHAIN_ROOT})
0184     if(ANDROID_TOOLCHAIN_PARSED)
0185         set(QT_ANDROID_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
0186         set(QT_ANDROID_TOOLCHAIN_VERSION ${CMAKE_MATCH_2})
0187     else()
0188         string(REGEX MATCH "${ANDROID_NDK}/toolchains/([^/]*)/prebuilt/([^/]*)" ANDROID_TOOLCHAIN_PARSED ${ANDROID_TOOLCHAIN_ROOT})
0189         if(ANDROID_TOOLCHAIN_PARSED)
0190             set(QT_ANDROID_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
0191         else()
0192             message(FATAL_ERROR "Failed to parse ANDROID_TOOLCHAIN_ROOT to get toolchain prefix and version")
0193         endif()
0194     endif()
0195     if(QT_ANDROID_TOOLCHAIN_PREFIX STREQUAL "llvm")
0196         set(QT_ANDROID_USE_LLVM "true")
0197     else()
0198         set(QT_ANDROID_USE_LLVM "false")
0199     endif()
0200     if(QT_ANDROID_TOOLCHAIN_PREFIX STREQUAL "x86")
0201         set(QT_ANDROID_TOOL_PREFIX "i686-linux-android")
0202     else()
0203         set(QT_ANDROID_TOOL_PREFIX ${QT_ANDROID_TOOLCHAIN_PREFIX})
0204     endif()
0205 
0206     # set the list of deployment-dependencies
0207     if(ARG_DEPLOYMENT_DEPENDS)
0208         set(DEPLOYMENT_DEPENDENCIES)
0209         foreach(DEP ${ARG_DEPLOYMENT_DEPENDS})
0210             if(DEPLOYMENT_DEPENDENCIES)
0211                 set(DEPLOYMENT_DEPENDENCIES "${DEPLOYMENT_DEPENDENCIES},${DEP}")
0212             else()
0213                 set(DEPLOYMENT_DEPENDENCIES "${DEP}")
0214             endif()
0215         endforeach()
0216         if(QT_ANDROID_APP_EXTRA_LIBS)
0217             set(QT_ANDROID_APP_EXTRA_LIBS "${QT_ANDROID_APP_EXTRA_LIBS}\n ")
0218         endif()
0219         set(QT_ANDROID_APP_EXTRA_LIBS "${QT_ANDROID_APP_EXTRA_LIBS}\"deployment-dependencies\": \"${DEPLOYMENT_DEPENDENCIES}\",")
0220     endif()
0221 
0222     # make sure that the output directory for the Android package exists
0223     file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI})
0224 
0225     # create the configuration file that will feed androiddeployqt
0226     configure_file(${QT_ANDROID_SOURCE_DIR}/qtdeploy.json.in ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json @ONLY)
0227 
0228     # check if the apk must be signed
0229     if(ARG_KEYSTORE)
0230         if(ARG_KEYSTORE STREQUAL "UNSIGNED_RELEASE")
0231             set(SIGN_OPTIONS --release)
0232         else()
0233             set(SIGN_OPTIONS --release --sign ${ARG_KEYSTORE} --tsa http://timestamp.digicert.com)
0234             if(ARG_KEYSTORE_PASSWORD)
0235                 set(SIGN_OPTIONS ${SIGN_OPTIONS} --storepass ${ARG_KEYSTORE_PASSWORD})
0236             endif()
0237         endif()
0238     endif()
0239 
0240     # check if the apk must be installed to the device
0241     if(ARG_INSTALL)
0242         set(INSTALL_OPTIONS --reinstall)
0243     endif()
0244 
0245     # specify the Android API level
0246     if(ANDROID_PLATFORM_LEVEL)
0247         set(TARGET_LEVEL_OPTIONS --android-platform android-${ANDROID_PLATFORM_LEVEL})
0248     endif()
0249 
0250     # create a custom command that will run the androiddeployqt utility to prepare the Android package
0251     add_custom_target(
0252         ${TARGET}
0253         ALL
0254         DEPENDS ${SOURCE_TARGET}
0255         COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI} # it seems that recompiled libraries are not copied if we don't remove them first
0256         COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI}
0257         COMMAND ${CMAKE_COMMAND} -E copy ${QT_ANDROID_APP_PATH} ${CMAKE_CURRENT_BINARY_DIR}/libs/${ANDROID_ABI}
0258         COMMAND ${QT_ANDROID_QT_ROOT}/bin/androiddeployqt --verbose --output ${CMAKE_CURRENT_BINARY_DIR} --input ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json --gradle ${TARGET_LEVEL_OPTIONS} ${INSTALL_OPTIONS} ${SIGN_OPTIONS}
0259     )
0260 
0261 endmacro()