A simple CMake utility for building and deploying Qt based applications on Android without QtCreator

Overview

Qt Android CMake utility

What it is

When using Qt for Android development, QMake & QtCreator is the only sane option for compiling and deploying. But if you prefer CMake, you're stuck and have no choice but writing .pro files that duplicate the functionality of your CMake files.

This utility tries to avoids this by providing a CMake way of doing Android compilation and deployment, without QtCreator. It is based on:

This utility has been developed for my own needs. Don't hesitate to use / share / fork / modify / improve it freely :)

How to use it

How to integrate it to your CMake configuration

The toolchain file defines the ANDROID variable, so that everything which is added specifically for Android in your CMake files can be surrounded with

if(ANDROID)
    ...
endif()

The first thing to do is to change your executable target into a library, because on Android, the entry point has to be a Java activity, and your C++ code is then loaded (as a library) and called by this activity.

if(ANDROID)
    add_library(my_app SHARED ...)
else()
    add_executable(my_app ...)
endif()

Then all you have to do is to call the add_qt_android_apk macro to create a new target that will create the Android APK.

if(ANDROID)
    include(qt-android-cmake/AddQtAndroidApk.cmake)
    add_qt_android_apk(my_app_apk my_app)
endif()

And that's it. Your APK can now be created by running "make" (or "cmake --build ." if you don't want to bother typing the full path to the make.exe program included in the NDK).

Of course, add_qt_android_apk accepts more options, see below for the detail.

How to run CMake

First, you must make sure that the following environment variables are defined:

  • ANDROID_NDK: root directory of the Android NDK
  • JAVA_HOME: root directory of the Java JDK

IMPORTANT JAVA_HOME must be defined when you compile the APK too.

Additionally you can define the following ones, but you can also define them as CMake variables if you prefer:

  • ANDROID_SDK: root directory of the Android SDK

You can then run CMake:.

On Windows

cmake -G"MinGW Makefiles"
      -DCMAKE_TOOLCHAIN_FILE="%ANDROID_NDK%/build/cmake/android.toolchain.cmake" 
      -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%/prebuilt/windows-x86_64/bin/make.exe" .

On Linux

cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .

On Mac OS X

This utility has not been tested on this OS yet :)

The Android toolchain can be customized with environment variables and/or CMake variables. Refer to its documentation (at the beginning of the toolchain file) for more details.

Options of the add_qt_android_apk macro

The first two arguments of the macro are the name of the APK target to be created, and the target it must be based on (your executable). These are of course mandatory.

The macro also accepts optional named arguments. Any combination of these arguments is valid, so that you can customize the generated APK according to your own needs.

Here is the full list of possible arguments:

NAME

The name of the application. If not given, the name of the source target is taken.

Example:

add_qt_android_apk(my_app_apk my_app
    NAME "My App"
)

VERSION_CODE

The internal version of the application. It must be a single number, incremented everytime your app is updated on the play store (otherwise it has no importance). If not given, the number 1 is used.

Note that the public version of the application, which is a different thing, is taken from the VERSION property of the CMake target. If none is provided, the VERSION_CODE number is used.

Example:

add_qt_android_apk(my_app_apk my_app
    VERSION_CODE 6
)

PACKAGE_NAME

The name of the application package. If not given, "org.qtproject.${source_target}" , where source_target is the name of the source target, is taken.

Example:

add_qt_android_apk(my_app_apk my_app
    PACKAGE_NAME "org.mycompany.myapp"
)

PACKAGE_SOURCES

The path to a directory containing additional files for the package (custom manifest, resources, translations, Java classes, ...). If you were using a regular QMake project file (.pro), this directory would be the one that you assign to the ANDROID_PACKAGE_SOURCE_DIR variable.

If you don't provide this argument, a default manifest is generated from the AndroidManifest.xml.in template and automatically used for building the APK.

If your PACKAGE_SOURCES directory contains a AndroidManifest.xml.in template file rather than a direct AndroidManifest.xml , it is automatically detected by the tool, configured and outputted as AndroidManifest.xml, so that you can still use the provided CMake variables in your custom manifest.

Example:

add_qt_android_apk(my_app_apk my_app
    PACKAGE_SOURCES ${CMAKE_CURRENT_LIST_DIR}/my-android-sources
)

KEYSTORE

The path to a keystore file and an alias, for signing the APK. If not provided, the APK won't be signed.

Example:

add_qt_android_apk(my_app_apk my_app
    KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/mykey.keystore myalias
)

KEYSTORE_PASSWORD

The password associated to the given keystore. Note that this option is only considered if the KEYSTORE argument is used. If it is not given, the password will be asked directly in the console at build time.

Example:

add_qt_android_apk(my_app_apk my_app
    KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/mykey.keystore myalias
    KEYSTORE_PASSWORD xxxxx
)

DEPENDS

A list of dependencies (libraries) to be included into the APK. All the dependencies of the application must be listed here; if one is missing, the deployed application will fail to run on the device. The listed items can be either target names, or library paths.

Example:

add_qt_android_apk(my_app_apk my_app
    DEPENDS a_linked_target "path/to/a_linked_library.so" etc.
)

APK_BUILD_TYPE

Android (.apk) build type: "release" or "debug". Possible values: "auto", "debug" and "release". By default, without setting APK_BUILD_TYPE explicitly value is "auto". "auto" cause setting APK_BUILD_TYPE depend on CMAKE_BUILD_TYPE.

INSTALL

If this option is given, the created APK will be deployed to a connected Android device. By default, the chosen device is the default one, i.e. the first one of the ADB device list.

Example:

add_qt_android_apk(my_app_apk my_app
    INSTALL
)

Troubleshooting

In case of

-- Configuring done
CMake Error in CMakeLists.txt:
  No known features for CXX compiler

  "GNU"

  version 4.9.

see Qt bug 54666 for details.

Contact

Laurent Gomila: [email protected]

Comments
  • New features

    New features

    This fork aim is to add new functionalities.

    • Customizable VERSION_NAME that can be set during the macro call.
    • Allow to deploy a mix between having a PACKAGE_SOURCES and using a configurable AndroidManifest.xml.in.
    • Specify a custom AndroidManifest.xml.in with ANDROID_MANIFEST_IN_PATH during the macro call.
    • Warning when a static or none ANDROID_STL is specified.
    • Move the minSdkVersion and targetSdkVersion from AndroidManifest.xml.in to a build.gradle.in to match new Android Policy.
    • Update the AndroidManifest.xml.in to the one in Qt5.12.x. qtandroiddeploy will add the required permission depending on what is deployed.
    • The apk is build inside a folder ${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_TARGET}-${ANDROID_ABI}.
    • Specify the --release or --debug flag to qtandroiddeploy.
      • --release : Release | MinSizeRel | RelWithDebInfo
      • --debug : Debug
    • --verbose can now be specified with the VERBOSE macro argument.

    For any question about this fork feel free to contact me.

    Tested with qt5.11 qt5.12 on windows 1803.

    opened by OlivierLDff 15
  • Use generator expressions for target locations; add LLVM/clang toolchain support.

    Use generator expressions for target locations; add LLVM/clang toolchain support.

    Fix issue #26:

    • Replace the use of LOCATION properties by generator expressions to acquire dependency target locations.
    • Add an extra file(GENERATOR) call to evaluate generator expressions at build time.
    opened by freekee1 9
  • Invoke add_qt_android_apk during install phase

    Invoke add_qt_android_apk during install phase

    I'd like to create an .apk in a single run, and have stripped libraries (no symbols) in the .apk. The command for that is "cmake ...; make install/strip". I specify the stripped libraries as dependencies in add_qt_android_apk. The stripping is done by cmake during install (after the ALL target), so add_qt_android_apk cannot run before it. This patch moves add_qt_android_apk from the ALL target to the install target.

    opened by Earthwings 6
  • Allow using a custom AndroidManifest.xml.in file

    Allow using a custom AndroidManifest.xml.in file

    To use a custom AndroidManifest.xml.in, pass it via the PACKAGE_MANIFEST argument of add_qt_android_apk. If PACKAGE_MANIFEST is not specified, AndroidManifest.xml.in from qt-android-cmake is used.

    opened by Earthwings 6
  • Add a way for the user to provide a custom gradle.build.in

    Add a way for the user to provide a custom gradle.build.in

    Since different version of qt use different version of gradle in the src/ folder, would it be possible to use our own gradle.build.in script.

    • Qt5.13: 'com.android.tools.build:gradle:3.2.0'
    • Qt5.14: 'com.android.tools.build:gradle:3.5.0'
    • Qt5.15: 'com.android.tools.build:gradle:3.6.0'

    I tried just to update the script to 3.6 but build break with Qt 5.13.

    Would you consider a PR that allow user to provide a build.gradle.in in the same way as AndroidManifest.xml.in ?

    opened by OlivierLDff 5
  • cmake regex error

    cmake regex error

    I get the following error, and so the script fails....

    Detected Android SDK build tools version 0.0.0 CMake Error at android/AddQtAndroidApk.cmake:161 (string): string sub-command REGEX, mode MATCH needs at least 5 arguments total to command. Call Stack (most recent call first): CMakeLists.txt:100 (add_qt_android_apk)

    This looks like its looking in the toolchain folder which for me has the following:

    aarch64-linux-android-4.9 arm-linux-androideabi-4.9 llvm renderscript x86-4.9

    opened by Gibbz 5
  • How to remove dependency to ministro system

    How to remove dependency to ministro system

    When I compile my app using this toolchain, it always make it dependent on ministro, asking me to download all Qt libraries through it. In qtcreator, there is an option to disable this, but how I do that in cmake option?

    opened by benapetr 5
  • fixes to get x86 build running

    fixes to get x86 build running

    the first commit, regarding the minSdkVersion, may be specific to the x86 ABI, ,and of course this can be handled by using a custom AndroidManifest.

    The second one, regarding qtdeploy.json, seems generic. The path that was constructed from the original value did not match on NDK 10 or 11, and for no prebuilt toolchain.

    opened by bergstr11 5
  • Allow passing a keystore file alias when signing a release apk

    Allow passing a keystore file alias when signing a release apk

    Allow passing a keystore file alias when signing a release apk because a release apk must be signed with a keystore file along with its alias.

    Signing a release apk, needs the alias as well. Just providing the keystore file does not seem to be enough. https://developer.android.com/studio/publish/app-signing?hl=ru#sign_release https://reactnative.dev/docs/signed-apk-android

    One could of course hack the ARG_KEYSTORE parameter and pass the keystore file along with appending the alias. But that is hackish. This PR allows the user of this tool to cleanly pass an alias for the keystore with a separate cmake argument.

    opened by isambitpujari 4
  • force ninja to show what is going on

    force ninja to show what is going on

    Without this patch ninja buffer "gradle" output and print it as whole after "gradle" finished. With this patch you see "gradle" progress online.

    opened by Dushistov 3
  • need option to unbind java release mode and C++ releasemode

    need option to unbind java release mode and C++ releasemode

    My project heavy enough to run it with CMAKE_BUILD_TYPE=Debug, slow start, slow redraw and so on. So everyday I use RelWithDebInfo mode, but at the same time I need apk build in debug mode to run it via IDE without any issues. So I need some new option to tell qt-android-cmake that I need debug mode anyway, even if CMAKE_BUILD_TYPE != Debug:

    if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND NOT ARG_KEYSTORE)
            set(QT_ANDROID_BUILD_TYPE --debug)
        else()
            set(QT_ANDROID_BUILD_TYPE --release)
        endif()
    
    opened by Dushistov 3
  • Too slow build in compare with Qt/qmake

    Too slow build in compare with Qt/qmake

    If I change one line of C++ code in my project and then run ninja project_apk it takes 39s, gradle output looks like this:

    ❯ grep Took /tmp/apk-build.log  | grep -v 'Took 0'
    :mergeDebugAssets (Thread[Execution worker for ':' Thread 30,5,main]) completed. Took 3.964 secs.
    :mergeDebugJniLibFolders (Thread[Execution worker for ':' Thread 30,5,main]) completed. Took 15.387 secs.
    :mergeDebugNativeLibs (Thread[Execution worker for ':' Thread 30,5,main]) completed. Took 15.046 secs.
    :stripDebugDebugSymbols (Thread[Execution worker for ':' Thread 30,5,main]) completed. Took 3.243 secs.
    

    as you can see the most time is spend during mergeDebug* tasks. In my ./project/project-arm64-v8a/libs/arm64-v8a/ there are 91 libraries from Qt, one my library and libc++_shared.

    So the most of the time I supposed is spend during handling of Qt libraries.

    The most strange part is that Qt libraries recreated every build. I disable this:

    @@ -303,8 +306,8 @@ macro(add_qt_android_apk TARGET SOURCE_TARGET)
             DEPENDS ${SOURCE_TARGET}
             ${QT_ANDROID_PRE_COMMANDS}
             # it seems that recompiled libraries are not copied if we don't remove them first
    -        COMMAND ${CMAKE_COMMAND} -E remove_directory ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}
    -        COMMAND ${CMAKE_COMMAND} -E make_directory ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}
    +#        COMMAND ${CMAKE_COMMAND} -E remove_directory ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}
    +#        COMMAND ${CMAKE_COMMAND} -E make_directory ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}
             COMMAND ${CMAKE_COMMAND} -E copy ${QT_ANDROID_APP_PATH} ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}
             COMMAND ${QT_ANDROID_QT_ROOT}/bin/androiddeployqt
             --verbose
    

    and build time changed to (editing the same file and rebuild project_apk):

    ❯ grep Took /tmp/apk-build2.log  | grep -v 'Took 0'
    :mergeDebugAssets (Thread[Execution worker for ':' Thread 13,5,main]) completed. Took 3.985 secs.
    :mergeDebugJniLibFolders (Thread[Execution worker for ':' Thread 13,5,main]) completed. Took 3.987 secs.
    :mergeDebugNativeLibs (Thread[Execution worker for ':' Thread 13,5,main]) completed. Took 3.994 secs.
    :javaPreCompileDebug (Thread[Execution worker for ':' Thread 12,5,main]) completed. Took 12.674 secs.
    

    So total gradle time changed from 39s to 14s.

    I read comment:

    it seems that recompiled libraries are not copied if we don't remove them first

    But my libproject_arm64-v8a.so updated even after commenting this lines, while "Qt libraries" not updated, and this is good.

    opened by Dushistov 0
  • Resource.qrc doesn't work

    Resource.qrc doesn't work

    Hello my resources arent work in android apk it doesnt gve error but added icons and etc are not showed except syle files

    styles/Devsion.qss styles/Hookmark.qss styles/SyNet.qss icons/backicon.png icons/back-icon2.svg

    This works: QFile styleFile(":/styles/SyNet.qss"); styleFile.open(QIODevice::ReadOnly); QString style(styleFile.readAll()); a.setStyleSheet(style);

    This doesn't work: ui->backButton->setIcon(QIcon(":/icons/back-icon2.svg"));

    Any ideas?

    opened by sufuk 3
Owner
Laurent Gomila
Laurent Gomila
CMake scripts for building OpenSceneGraph third party libraries.

osg-3rdparty-cmake CMake scripts for building OpenSceneGraph third party libraries. These scripts can be used to build third party libraries from sour

Björn Blissing 157 Dec 25, 2022
CMake module for building Windows Installer packages with WiX toolset

FindWiX CMake module for building Windows Installer packages with WiX toolset Introduction Requirements Usage find_package() wix_add_project() WiX com

Apriorit Inc. 11 Aug 5, 2022
CMake find module for Intel Threading Building Blocks

FindTBB Module FindTBB is a CMake find package module for Intel® Threading Building Blocks (TBB). Usage The signature of the TBB find module in CMake

Justus Calvin 84 Dec 3, 2022
A set of cmake modules to assist in building code

CMake 3 Tools Warning: These tools are being replaced by the Modern CMake. Some of the tools are still being maintained for now, but new projects shou

null 201 Dec 21, 2022
Utility and common library for all polysquare cmake tools.

Polysquare CMake Tooling Utility Functions Utility and common library for all polysquare cmake tools. Status Travis CI (Ubuntu) AppVeyor (Windows) Cov

ポリ平方 POLYSQUARE 3 May 7, 2021
CMake scripts for painless usage of SuiteSparse+METIS from Visual Studio and the rest of Windows/Linux/OSX IDEs supported by CMake

CMake scripts for painless usage of Tim Davis' SuiteSparse (CHOLMOD,UMFPACK,AMD,LDL,SPQR,...) and METIS from Visual Studio and the rest of Windows/Lin

Jose Luis Blanco-Claraco 395 Dec 24, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

HPC 82 Nov 30, 2022
unmaintained - CMake module to activate certain C++ standard, feature checks and appropriate automated workarounds - basically an improved version of cmake-compile-features

Compatibility This library provides an advanced target_compile_features() and write_compiler_detection_header(). The problem with those is that they a

Jonathan Müller 74 Dec 26, 2022
CMake toolchain file and other scripts for the Android NDK

android-cmake CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on

Andrey Kamaev 1.2k Jan 7, 2023
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

CPM.cmake 1.6k Jan 9, 2023
CMake checks cache helper modules – for fast CI CMake builds!

cmake-checks-cache Cross platform CMake projects do platform introspection by the means of "Check" macros. Have a look at CMake's How To Write Platfor

Cristian Adam 65 Dec 6, 2022
cmake-font-lock - Advanced, type aware, highlight support for CMake

cmake-font-lock - Advanced, type aware, highlight support for CMake

Anders Lindgren 39 Oct 2, 2022
cmake-avr - a cmake toolchain for AVR projects

cmake-avr - a cmake toolchain for AVR projects Testing the example provided The toolchain was created and tested within the following environment: Lin

Matthias Kleemann 163 Dec 5, 2022
Make CMake less painful when trying to write Modern Flexible CMake

Izzy's eXtension Modules IXM is a CMake library for writing Modern flexible CMake. This means: Reducing the amount of CMake written Selecting reasonab

IXM 107 Sep 1, 2022
[CMake] [BSD-2] CMake module to find ICU

FindICU.cmake A CMake module to find International Components for Unicode (ICU) Library Note that CMake, since its version 3.7.0, includes a FindICU m

julp 29 Nov 2, 2022
Simple library for embedding static resources into C++ binaries using CMake

libromfs libromfs is an easy way to bundle resources directly into any C++ application and access them through a simple interface. The main advantage

WerWolv 28 Nov 30, 2022
This is a simple CMake tutorial project which contains some different scenarios

learning-cmake This is a simple CMake tutorial project which contains some different scenarios. hello-world: Demo a simplest CMake project. hello-worl

Bob Liu 2.9k Jan 9, 2023
A program that automatically generates CMake and Meson configuration files for your Vala project

Autovala is a program and a library designed to help in the creation of projects with Vala and CMake. It also has support for Genie.

Sergio Costas 108 Oct 15, 2022
A template C++ repository, using CMake and Catch

C++ Project Template This is a template project for C++. It uses CMake to build and Catch for unit tests. It is integrated with Travis CI, and builds

Joshua Peterson 49 Oct 23, 2022