diff options
| -rw-r--r-- | CMakeLists.txt | 4 | ||||
| -rw-r--r-- | toolchain/Android.cmake | 183 | ||||
| -rw-r--r-- | toolchain/deployment-file.json.in | 15 | 
3 files changed, 202 insertions, 0 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index b230bb28..6bccfbc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ if(BUILD_TESTING)  endif()  set(SHARE_INSTALL_DIR share) +set(TOOLCHAIN_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/toolchain/)  set(MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/modules/)  set(KDE_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/kde-modules/)  set(FIND_MODULES_INSTALL_DIR ${SHARE_INSTALL_DIR}/ECM/find-modules/) @@ -33,6 +34,9 @@ install(FILES ${installKdeModuleFiles} DESTINATION ${KDE_MODULES_INSTALL_DIR})  file(GLOB installFindModuleFiles ${CMAKE_SOURCE_DIR}/find-modules/*[^~])  install(FILES ${installFindModuleFiles} DESTINATION ${FIND_MODULES_INSTALL_DIR}) +file(GLOB installToolchainModuleFiles ${CMAKE_SOURCE_DIR}/toolchain/*[^~]) +install(FILES ${installToolchainModuleFiles} DESTINATION ${TOOLCHAIN_MODULES_INSTALL_DIR}) +  include(CMakePackageConfigHelpers) diff --git a/toolchain/Android.cmake b/toolchain/Android.cmake new file mode 100644 index 00000000..8272ef9d --- /dev/null +++ b/toolchain/Android.cmake @@ -0,0 +1,183 @@ +#.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. +# +# Note: Requires CMake 3.1 +# +# How to use it? +# -------------- +# First of all, to make use of this toolchain file it's required to specify the +# CMAKE_TOOLCHAIN_FILE variable pointing to AndroidToolchain.cmake. +# +# Then, there's many settings that we may want to specify under what circumstances +# the project will be built. This will be done through environment variables: +# - ANDROID_NDK: points to the NDK root path +# - ANDROID_SDK_ROOT: points to the SDK root path +# +# Also there's some cache variables we can pass as well to narrow down the +# preferred settings: +# - ANDROID_NDK: Points to the NDK root, defaults to the environment variable +# with the same name. +# - ANDROID_SDK_ROOT: Points to the Android SDK root, defaults to the environment +# variable with the same name. +# - ANDROID_ARCHITECTURE: Specifies the used architecture, "arm" by default. See +# arch-* directory. +# - ANDROID_TOOLCHAIN: Specifies the toolchain to be used. Defaults to +# "arm-linux-androideabi". See <ndk>/toolchains/ directory. +# - ANDROID_ABI: Specifies the ABI to be used. Defaults to "armeabi-v7a". See +# <ndk>/sources/cxx-stl/gnu-libstdc++/*/libs/ directories. +# - ANDROID_GCC_VERSION: Specifies the GCC version. Defaults to "4.9". +# - ANDROID_API_LEVEL: Specifies the API level to require. Defaults to "14". See +# http://developer.android.com/guide/topics/manifest/uses-sdk-element.html +# - ANDROID_SDK_BUILD_TOOLS_REVISION: Specifies the build tools version to be used. +# Defaults to "21.1.1". +# +# Once we have the application built, we will want to generate an APK that we +# can run on an Android device. To this end we've integrated androiddeployqt so +# this can be done easily. This won't work with non-qt projects. +# To make use of the APK generation, we'll define QTANDROID_EXPORTED_TARGET with +# the target we want to have exported. +# Additionally, we'll need to specify a ANDROID_APK_DIR with the base information +# to set the project up. For more information see: +# https://qt-project.org/doc/qt-5-snapshot/deployment-android.html +# +# Once set up, after building, make create-apk-<target_name> will process this +# input and generate an apk that can be found inside the build directory: +# ${CMAKE_BINARY_DIR}/<target_name>_build_apk/bin/QtApp-*.apk. +# +# ============================================================================= +# Copyright 2014 Aleix Pol i Gonzalez <aleixpol@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of extra-cmake-modules, substitute the full +#  License text for the above reference.) + +cmake_minimum_required(VERSION "3.1") + +#input +set(ANDROID_NDK "$ENV{ANDROID_NDK}" CACHE path "Android NDK path") +set(ANDROID_SDK_ROOT "$ENV{ANDROID_SDK_ROOT}" CACHE path "Android SDK path") +set(ANDROID_ARCHITECTURE "arm" CACHE string "Used Architecture, related to the ABI and TOOLCHAIN") +set(ANDROID_TOOLCHAIN "arm-linux-androideabi" CACHE string "Used SDK") +set(ANDROID_ABI "armeabi-v7a" CACHE string "Used ABI") +set(ANDROID_GCC_VERSION "4.9" CACHE string "Used GCC version" ) +set(ANDROID_API_LEVEL "14" CACHE string "Android API Level") +set(ANDROID_SDK_BUILD_TOOLS_REVISION "21.1.1" CACHE string "Android API Level") + +set(_HOST "${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}") +string(TOLOWER "${_HOST}" _HOST) + +get_filename_component(_CMAKE_ANDROID_DIR "${CMAKE_TOOLCHAIN_FILE}" PATH) + +cmake_policy(SET CMP0011 OLD) +cmake_policy(SET CMP0017 OLD) + +set(CMAKE_SYSROOT +    "${ANDROID_NDK}/platforms/android-${ANDROID_API_LEVEL}/arch-${ANDROID_ARCHITECTURE}") +if(NOT EXISTS ${CMAKE_SYSROOT}) +    message(FATAL_ERROR "Couldn't find the Android NDK Root in ${CMAKE_SYSROOT}") +endif() + +#actual code +SET(CMAKE_SYSTEM_NAME Android) +SET(CMAKE_SYSTEM_VERSION 1) + +set(ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN}-${ANDROID_GCC_VERSION}/prebuilt/${_HOST}/bin") +set(ANDROID_LIBS_ROOT "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_GCC_VERSION}") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM "${ANDROID_TOOLCHAIN_ROOT}") +set(ANDROID_LIBRARIES_PATH +    "${CMAKE_SYSROOT}/usr/lib") +set(CMAKE_SYSTEM_LIBRARY_PATH +    ${ANDROID_LIBRARIES_PATH} +    "${ANDROID_LIBS_ROOT}/libs/${ANDROID_ABI}/" +) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so") +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +find_library(GNUSTL_SHARED gnustl_shared) +if(NOT GNUSTL_SHARED) +    message(FATAL_ERROR "you need gnustl_shared: ${CMAKE_SYSTEM_LIBRARY_PATH}") +endif() +include_directories(SYSTEM +    "${CMAKE_SYSROOT}/usr/include" +    "${ANDROID_LIBS_ROOT}/include/" +    "${ANDROID_LIBS_ROOT}/libs/${ANDROID_ABI}/include" +) + +link_directories(${CMAKE_SYSTEM_LIBRARY_PATH}) + +set(CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN}-gcc") +set(CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN}-g++") + +SET(CMAKE_FIND_ROOT_PATH ${ANDROID_NDK}) +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_EXE_LINKER_FLAGS "${GNUSTL_SHARED} -Wl,-rpath-link,${ANDROID_LIBRARIES_PATH} -llog -lz -lm -ldl -lc -lgcc" CACHE STRING "") +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "") +set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "") + +#we want executables to be shared libraries, hooks will invoke the exported cmake function +set(CMAKE_CXX_LINK_EXECUTABLE +    "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" +) + +######### generation + +set(CREATEAPK_TARGET_NAME "create-apk-${QTANDROID_EXPORTED_TARGET}") +if(DEFINED QTANDROID_EXPORTED_TARGET AND NOT TARGET ${CREATEAPK_TARGET_NAME}) +    if(NOT EXISTS "${ANDROID_APK_DIR}/AndroidManifest.xml") +        message(FATAL_ERROR "Define an apk dir to initialize from using -DANDROID_APK_DIR=<path>. The specified directory must contain the AndroidManifest.xml file.") +    endif() + +    function(EOFHook) +        if(CMAKE_PARENT_LIST_FILE STREQUAL "") +            generate_deployment_file() +        endif() +    endfunction() + +    function(generate_deployment_file) +        get_property(_DEPENDENCIES TARGET ${QTANDROID_EXPORTED_TARGET} PROPERTY INTERFACE_LINK_LIBRARIES) +        set(_DEPS_LIST) +        foreach(_DEP IN LISTS _DEPENDENCIES) +            if(NOT _DEP MATCHES "Qt5::.*") +                get_property(_DEP_LOCATION TARGET ${_DEP} PROPERTY "LOCATION_${CMAKE_BUILD_TYPE}") +                list(APPEND _DEPS_LIST ${_DEP_LOCATION}) +            endif() +        endforeach() +        string(REPLACE ";" "," _DEPS "${_DEPS_LIST}") +        configure_file("${_CMAKE_ANDROID_DIR}/deployment-file.json.in" "${QTANDROID_EXPORTED_TARGET}-deployment.json") +    endfunction() + +#   Create the target that will eventually generate the apk +    get_filename_component(QTDIR "${Qt5Core_DIR}/../../../" ABSOLUTE) +    find_program(ANDROID_DEPLOY_QT androiddeployqt HINTS "${QTDIR}/bin") +    set(EXPORT_DIR "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}_build_apk/") +    set(EXECUTABLE_DESTINATION_PATH "${EXPORT_DIR}/libs/${ANDROID_ABI}/lib${QTANDROID_EXPORTED_TARGET}.so") + +    add_custom_target(${CREATEAPK_TARGET_NAME} +        COMMAND cmake -E echo "Generating $<TARGET_NAME:${QTANDROID_EXPORTED_TARGET}> with ${ANDROID_DEPLOY_QT}" +        COMMAND cmake -E copy_directory "${ANDROID_APK_DIR}" "${EXPORT_DIR}" +        COMMAND cmake -E copy "$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" "${EXECUTABLE_DESTINATION_PATH}" +        COMMAND ${ANDROID_DEPLOY_QT} --input "${QTANDROID_EXPORTED_TARGET}-deployment.json" --output "${EXPORT_DIR}" --deployment bundled "\\$(ARGS)" +    ) + +    #we want to call the function after the project has been set up +    variable_watch(CMAKE_PARENT_LIST_FILE EOFHook) +else() +    message(STATUS "You can export a target by specifying -DQTANDROID_EXPORTED_TARGET=<targetname>") +endif() diff --git a/toolchain/deployment-file.json.in b/toolchain/deployment-file.json.in new file mode 100644 index 00000000..e662795a --- /dev/null +++ b/toolchain/deployment-file.json.in @@ -0,0 +1,15 @@ +{ +   "qt": "@QTDIR@", +   "sdk": "@ANDROID_SDK_ROOT@", +   "ndk": "@ANDROID_NDK@", +   "toolchain-prefix": "@ANDROID_TOOLCHAIN@", +   "tool-prefix": "@ANDROID_TOOLCHAIN@", +   "toolchain-version": "@ANDROID_GCC_VERSION@", +   "ndk-host": "@_HOST@", +   "target-architecture": "@ANDROID_ABI@", +   "application-binary": "@EXECUTABLE_DESTINATION_PATH@", +   "android-extra-libs": "@_DEPS@", +   "android-extra-plugins": "@CMAKE_PREFIX_PATH@/share,@CMAKE_PREFIX_PATH@/lib/qml", +   "android-package-source-directory": "@ANDROID_APK_DIR@", +   "sdkBuildToolsRevision": "@ANDROID_SDK_BUILD_TOOLS_REVISION@" +} | 
