Targeting Android on a Windows development machine

The Android NDK is a toolset that lets you implement parts of your Android application in C or C++.

The native libraries are built using CMake.

As of NDK 16 the gcc compiler is no longer supported, so we only use the clang compiler, by setting the CMake variable ANDROID_TOOLCHAIN to the value "clang".

The NDK allows for building both shared (.so) and static (.a) libraries according to the value of the CMake variable CMAKE_BUILD_TYPE.

Build steps

In the following diagram input source code is shown in light blue, outputs are shown in dark blue and build processes are shown in green.

A build using cmake+NDK compiles C++ code, and links input libraries and object files to generate output libraries for a particular ABI such as arm64-v8a. All but one of these invocations of cmake are made from windows batch files. Only one is invoked by the Android Studio build system (which uses Gradle).

A Python script provided by the pyceda python package generates the JNI C++/Java code from the reflection information in the pypizza package.

Installing Android NDK

First install Android Studio. Version 3.4.1 for Windows 64-bit is 971 MB. This is an IDE which allows for developing applications that run on Android devices. These applications are often written in Java.

Android Studio has the Android SDK Manager which helps you download the SDK tools, platforms, and other components you need to develop your apps.

In particular the Android SDK Manager can download and install the Android NDK for you.

Setting CMake variables to control the build

There are a number of CMake variables that can be set to control the build when using the NDK

For details see the Android Developers NDK Guide on using CMake

ABI

See the Android Developers NDK guide on ABI Management.

For now we only support the arm64-v8a ABI, which supports the AArch64 instruction set. This is specified by setting the CMake variable ANDROID_ABI to the value "arm64-v8a".

This ABI is for ARMv8-based CPUs that support AArch64. It also includes the NEON and VFPv4 instruction sets.

Note that 64-bit devices also support their 32-bit variants. Using arm64-v8a devices as an example, the device can also run armeabi and armeabi-v7a code.

Issue with find_package() not finding CEDA when targeting Android

Unfortunately when the android NDK tool chain is used, find_package fails, as though the CMake System Package Registry is ignored.

The workaround is to set a CMake variable named Ceda_DIR when invoking cmake. Typically Ceda_DIR should be set to C:\Program Files\Ceda\cmake.

todo: although this works, it might be better to instead set a CMake variable named Ceda_ROOT as this is more clearly stated in the documentation for find_package:

Search paths specified in the <PackageName>_ROOT CMake variable and the <PackageName>_ROOT environment variable, where <PackageName> is the package to be found.

A batch file might invoke cmake like this:


    :: abi can be one of:
    ::     arm64-v8a
    ::     armeabi-v7a
    ::     x86
    ::     x86_64
    ::
    :: config can be one of:
    ::     RelWithDebInfo
    ::     Debug
    ::
    :: libtype can be one of:
    ::     shared
    ::     static
    ::
    

    SET NDK="%LOCALAPPDATA%/Android/Sdk/ndk-bundle"

    cmake -G "Ninja" ^
        -DCeda_DIR="%ProgramFiles%/Ceda/cmake" ^
        -DCEDA_CUSTOM_BUILD_ANDROID=ON ^
        -DBUILD_SHARED_LIBS=%SHARED_LIBS% ^
        -DCMAKE_INSTALL_PREFIX:PATH="install" ^
        -DANDROID_ABI=%ABI% ^
        -DANDROID_NDK=%NDK% ^
        -DCMAKE_BUILD_TYPE=%CONFIG% ^
        -DCMAKE_MAKE_PROGRAM=ninja ^
        -DCMAKE_TOOLCHAIN_FILE="%NDK%/build/cmake/android.toolchain.cmake" ^
        -DANDROID_NATIVE_API_LEVEL="21" ^
        -DANDROID_TOOLCHAIN="clang" ^
        -DCMAKE_CXX_FLAGS=-fPIC -frtti -fexceptions -std=c++17 ^
        --config %CONFIG% ^
        "%SOURCE%"

    cmake --build . --target install --config %CONFIG%

CEDA_CUSTOM_BUILD_ANDROID

See build boost for android.

CEDA_CUSTOM_BUILD_ANDROID is only needed for allowing our own version of boost to be used. (static boost for android libraries were built on Windows with clang, ndk 19r using our own bash script 'buildboostandroid_linux' or 'buildboostandroid_windows' running under git bash).

It not clear how to make our own build of boost work with Kitware's undocumented FindBoost.cmake We can probably make it work, Cameron Lowell Palmer claims it can be done on stackoverflow but he says the following which is a bit off-putting:

Let me start by saying getting CMake to find Boost can be difficult because the automagic in FindBoost.cmake will bite you and KitWare the makers of CMake have some of the worst documentation of any popular project I've ever encountered. You'll have to walk through the source of FindBoost.cmake to debug it if it fails.