aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleix Pol <aleixpol@kde.org>2015-02-06 01:24:23 +0100
committerAleix Pol <aleixpol@kde.org>2015-02-06 01:24:23 +0100
commit5b39c909baeb3e4c247a43b91a884d5990c99092 (patch)
tree6b2c21fe67bcfc7c803c065ff27cbfcbc4d621f8
parentb03e287f9abe95372b0bc1b1917a006447280c95 (diff)
downloadextra-cmake-modules-5b39c909baeb3e4c247a43b91a884d5990c99092.tar.gz
extra-cmake-modules-5b39c909baeb3e4c247a43b91a884d5990c99092.tar.bz2
Move Android toolchain module to ECM
Introduces the new Android toolchain file for being able to easily compile our cmake projects in Android, with an emphasis on Qt projects. CHANGELOG: New Android toolchain support module. REVIEW: 121545
-rw-r--r--CMakeLists.txt4
-rw-r--r--toolchain/Android.cmake183
-rw-r--r--toolchain/deployment-file.json.in15
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@"
+}