aboutsummaryrefslogtreecommitdiff
path: root/toolchain/Android.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain/Android.cmake')
-rw-r--r--toolchain/Android.cmake183
1 files changed, 183 insertions, 0 deletions
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()