Browse Source

Android: make this work again with NDK r19+ and CMake 3.16+.

Also updating the docs to use system 24 instead of 22 as that's the
first version with Vulkan support; plus other random updates and add a
bunch of new troubleshootings.
pull/454/head
Vladimír Vondruš 6 years ago
parent
commit
8bc1fa154d
  1. 36
      doc/building.dox
  2. 104
      doc/platforms-android.dox
  3. 11
      package/archlinux/PKGBUILD-android-arm64

36
doc/building.dox

@ -690,8 +690,9 @@ installed files. The following variables are supported:
scripts and other files are installed. CMake on Android by default searches scripts and other files are installed. CMake on Android by default searches
for binaries in <tt>&lt;ndk&gt;/platforms/android-&lt;api&gt;/arch-&lt;arch&gt;/usr</tt> for binaries in <tt>&lt;ndk&gt;/platforms/android-&lt;api&gt;/arch-&lt;arch&gt;/usr</tt>
based on target API and platform, but looks for headers in a central based on target API and platform, but looks for headers in a central
location at <tt>&lt;ndk&gt;/sysroot/usr</tt>. Defaults to ``.``. If a location at <tt>&lt;ndk&gt;/toolchains/llvm/prebuilt/&lt;host&gt;/sysroot/usr</tt>.
relative path is used, it's relative to `CMAKE_INSTALL_PREFIX`. Defaults to ``.``. If a relative path is used, it's relative to
`CMAKE_INSTALL_PREFIX`.
Various plugin interfaces search for plugins in locations and order documented Various plugin interfaces search for plugins in locations and order documented
in @ref Corrade::PluginManager::implicitPluginSearchPaths(), in @ref Corrade::PluginManager::implicitPluginSearchPaths(),
@ -1027,15 +1028,13 @@ to make it available to depending projects.
You will need [Android NDK](https://developer.android.com/ndk/) installed and You will need [Android NDK](https://developer.android.com/ndk/) installed and
configured and @ref building-corrade-cross-android "Corrade built for Android". configured and @ref building-corrade-cross-android "Corrade built for Android".
At least CMake 3.7 is required, as it has Android support built-in. The The guide assumes NDK r19+ with unified Clang toolchain, which in turn requires
supported toolchain is now Clang with libc++, GCC is not supported anymore. at least CMake 3.16.
Create a build directory and run `cmake` and the build command in it. Set Create a build directory and run `cmake` and the build command in it. Set
`CMAKE_SYSTEM_NAME` to `Android` to enable the crosscompilation, `CMAKE_SYSTEM_NAME` to `Android` to enable the crosscompilation,
`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION` and `CMAKE_ANDROID_STL_TYPE` to use Clang `CMAKE_ANDROID_STL_TYPE` to use libc++, `CMAKE_SYSTEM_VERSION` to minimal API version level you wish to use and `CMAKE_ANDROID_ARCH_ABI` to target platform
with libc++, `CMAKE_SYSTEM_VERSION` to minimal API version level you wish to ABI. Check the [CMake Android cross-compiling documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android)
use and `CMAKE_ANDROID_ARCH_ABI` to target platform ABI. Check the
[CMake Android cross-compiling documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android)
for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if
@ref building-cross-corrade-rc "natively-built corrade-rc" is accessible @ref building-cross-corrade-rc "natively-built corrade-rc" is accessible
through `PATH`. through `PATH`.
@ -1044,26 +1043,31 @@ If you set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of the particular
Android platform sysroot, the package will get found automatically when Android platform sysroot, the package will get found automatically when
compiling depending projects. Gradle and other Android buildsystems expect compiling depending projects. Gradle and other Android buildsystems expect
platform-independent includes and other files to be stored in a central platform-independent includes and other files to be stored in a central
location, you can set `MAGNUM_INCLUDE_INSTALL_PREFIX` to `/usr` subdirectory of location, you can point `MAGNUM_INCLUDE_INSTALL_PREFIX` there to install the
the global NDK sysroot. Another option is to explicitly set `CMAKE_PREFIX_PATH` includes separately. Another option is to explicitly set `CMAKE_PREFIX_PATH`
to the install location in depending projects. to the install location in depending projects. Unfortunately, CMake needs extra
help with `CMAKE_FIND_ROOT_PATH` to correctly find Android libraries, otherwise
it falls back to looking in native system locations. Adapt them to your
system, Android ABI and version and NDK location as needed.
Note that `BUILD_STATIC` is implicitly enabled, because manually loading all Note that `BUILD_STATIC` is implicitly enabled, because manually loading all
depending shared libraries using JNI would be too inconvenient. The engine is depending shared libraries using JNI would be too inconvenient. The engine is
built for OpenGL ES 2.0 by default, switch to 3.0 by disabling `TARGET_GLES2`. built for OpenGL ES 2.0 by default, switch to 3.0 by disabling `TARGET_GLES2`.
@m_class{m-console-wrap}
@code{.sh} @code{.sh}
mkdir build-android-arm64 && cd build-android-arm64 mkdir build-android-arm64 && cd build-android-arm64
cmake .. \ cmake .. \
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=22 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-22/arch-arm/usr \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm/usr \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DCORRADE_RC_EXECUTABLE=/path/to/corrade-rc \ -DCORRADE_RC_EXECUTABLE=/path/to/corrade-rc \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/sysroot/usr \ -DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DTARGET_GLES2=OFF \ -DTARGET_GLES2=OFF \
-DWITH_ANDROIDAPPLICATION=ON -DWITH_ANDROIDAPPLICATION=ON
cmake --build . cmake --build .

104
doc/platforms-android.dox

@ -38,10 +38,10 @@ namespace Magnum {
The following guide explains how to build Android projects using minimal The following guide explains how to build Android projects using minimal
command-line tools, without Android Studio involved. command-line tools, without Android Studio involved.
At the very least you need to have Android SDK and Android NDK installed. At the very least you need to have Android SDK and Android NDK installed, the guide assumes NDK r19 and newer. Running console utilities and tests on the
Running console utilities and tests on the device don't need much more, in case device don't need much more, in case you want to develop actual applications,
you want to develop actual applications, you need also the SDK and a platform + you need also the SDK and a platform + SDK platform build tools for version of
SDK platform build tools for version of your choice. your choice.
For APK building it's possible to use either an experimental support in CMake For APK building it's possible to use either an experimental support in CMake
or the official way with Gradle. Gradle is able to download all the or the official way with Gradle. Gradle is able to download all the
@ -55,30 +55,36 @@ for a cleaner setup.
- [android-ndk](https://aur.archlinux.org/packages/android-ndk/) - [android-ndk](https://aur.archlinux.org/packages/android-ndk/)
- [android-sdk-build-tools](https://aur.archlinux.org/packages/android-sdk-build-tools/) - [android-sdk-build-tools](https://aur.archlinux.org/packages/android-sdk-build-tools/)
- [android-sdk-platform-tools](https://aur.archlinux.org/packages/android-sdk-platform-tools/) - [android-sdk-platform-tools](https://aur.archlinux.org/packages/android-sdk-platform-tools/)
- [android-platform-22](https://aur.archlinux.org/packages/android-platform-22/) - [android-platform-24](https://aur.archlinux.org/packages/android-platform-24/)
- [android-sdk-cmake](https://aur.archlinux.org/packages/android-sdk-cmake/) - [android-sdk-cmake](https://aur.archlinux.org/packages/android-sdk-cmake/)
Gradle requires Android SDK version of CMake, which is currently at version Gradle requires Android SDK version of CMake, which is currently at version
3.6. See below for an experimental way to @ref platforms-android-system-cmake "use the system CMake" 3.10. See below for an experimental way to @ref platforms-android-system-cmake "use the system CMake"
instead. On the other hand, while it's possible to use the CMake from Android instead. On the other hand, while it's possible to use the CMake from Android
SDK to build Magnum itself, the following guide is written with CMake 3.7 and SDK to build Magnum itself, the following guide is written with CMake 3.16 and
newer in mind, which has Android support built-in. In older versions you'd need newer in mind, which has Android NDK r19+ support built-in. In older versions
to supply a toolchain file instead and the configuration values are different. you'd need to supply a toolchain file instead and the configuration values are
different.
@section platforms-android-console Building and running console applications @section platforms-android-console Building and running console applications
Android allows to run arbitrary console utilities and tests via ADB. Assuming Android allows to run arbitrary console utilities and tests via ADB. Assuming
you have Magnum installed in the NDK path as described in @ref building-cross-android, you have Magnum installed in the NDK path as described in @ref building-cross-android,
build your project simply as this (adapt version numbers and ABIs as needed): build your project as below. The `CMAKE_FIND_ROOT_PATH` is unfortunately needed
for CMake to correctly find Android libraries, otherwise it falls back to
looking in native system locations. Adapt paths to your system, Android ABI and
version and NDK location as needed:
@m_class{m-console-wrap}
@code{.sh} @code{.sh}
mkdir build-android-arm64 && cd build-android-arm64 mkdir build-android-arm64 && cd build-android-arm64
cmake .. \ cmake .. \
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=22 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release
cmake --build . cmake --build .
@endcode @endcode
@ -87,10 +93,11 @@ After that you can use ADB to upload your executable to the device and run it
there. The global temporary directory is `/data/local/tmp` and while the parent there. The global temporary directory is `/data/local/tmp` and while the parent
directories often don't have permissions, it's possible to @cb{.sh} cd @ce into directories often don't have permissions, it's possible to @cb{.sh} cd @ce into
it and create arbitrary files there. Assuming you built an executable in it and create arbitrary files there. Assuming you built an executable in
`build-android-arm64/src/my-application`, the workflow would be like this: `build-android-arm64/Release/bin/my-application`, the workflow would be like
this:
@code{.sh} @code{.sh}
adb push build-android-arm64/src/my-application /data/local/tmp adb push build-android-arm64/Release/bin/my-application /data/local/tmp
adb shell /data/local/tmp/my-application adb shell /data/local/tmp/my-application
@endcode @endcode
@ -404,17 +411,19 @@ After that, you can add the additional ABIs to the `abiFilters` list in your
For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24 For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24
could look like this: could look like this:
@m_class{m-console-wrap}
@code{.sh} @code{.sh}
mkdir build-android-arm && cd build-android-arm mkdir build-android-arm && cd build-android-arm
cmake .. \ cmake .. \
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \ -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm/usr \ -DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm/usr \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/sysroot/usr -DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr
cmake --build . --target install cmake --build . --target install
cd .. cd ..
@ -424,11 +433,11 @@ cmake .. \
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm64/usr \ -DCMAKE_INSTALL_PREFIX=<ndk>/platforms/android-24/arch-arm64/usr \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/sysroot/usr -DCMAKE_FIND_ROOT_PATH="<ndk>platforms/android-24/arch-arm64;<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=<ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr
cmake --build . --target install cmake --build . --target install
@endcode @endcode
@ -502,7 +511,7 @@ $ adb logcat *:S magnum
According to the [official documentation](https://developer.android.com/studio/projects/add-native-code.html#vanilla_cmake), According to the [official documentation](https://developer.android.com/studio/projects/add-native-code.html#vanilla_cmake),
it's possible to use system CMake installation without needing to install it's possible to use system CMake installation without needing to install
Android SDK version of CMake 3.6. Simply update the Android SDK version of CMake 3.10. Simply update the
@cb{.gradle} externalNativeBuild @ce in your `build.gradle` file to specify @cb{.gradle} externalNativeBuild @ce in your `build.gradle` file to specify
CMake version that you have installed in your system, for example: CMake version that you have installed in your system, for example:
@ -513,15 +522,13 @@ android {
cmake { cmake {
path 'CMakeLists.txt' path 'CMakeLists.txt'
... ...
version '3.10.2' version '3.17'
} }
} }
} }
@endcode @endcode
However, be aware that this is an experimental feature and may be broken. At However, be aware that this is an experimental feature and may be broken.
the time of writing (March 2018), it didn't work for me with NDK r16b, Android
buid plugin 3.0.1 and CMake 3.10.
@section platforms-android-gradlew Using gradlew wrappers instead of a system installation @section platforms-android-gradlew Using gradlew wrappers instead of a system installation
@ -743,19 +750,52 @@ gradle build
@section platforms-android-troubleshooting Troubleshooting @section platforms-android-troubleshooting Troubleshooting
@subsection platforms-android-cmake-too-old CMake is too old @subsection platforms-android-cmake-too-old CMake or NDK is too old
While the minimal CMake version that's required for building Magnum for Android While the minimal CMake version that's required for building Magnum for Android
is 3.7, you might want to grab at least CMake 3.9.2, as it is 3.7, NDK r19 and newer need at least CMake 3.16 to work. For older NDKs you
[fixes an issue with the Clang toolchain](https://gitlab.kitware.com/cmake/cmake/issues/17253). might want to grab at least CMake 3.9.2, as it [fixes an issue with the Clang toolchain](https://gitlab.kitware.com/cmake/cmake/issues/17253).
With NDK r18 and older you'll need to additionally supply
`-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang`, on the other hand the
`-DCMAKE_FIND_ROOT_PATH` isn't needed --- CMake is able to figure out the paths
on its own in that case.
@subsection platforms-android-ndk-too-new NDK is too new @subsection platforms-android-compiler-fails-at-life Compiler suddenly fails at life
If you're suddenly greeted with an overwhelming amount of strange errors coming
from standard library C++ headers including things like
@m_class{m-console-wrap}
@code{.shell-session}
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:319:9: error: no member named 'isnormal' in the global namespace
using ::isnormal;
~~^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:320:9: error: no member named 'isgreater' in the global namespace
using ::isgreater;
~~^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:321:9: error: no member named 'isgreaterequal' in the global namespace
using ::isgreaterequal;
~~^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:322:9: error: no member named 'isless' in the global namespace
using ::isless;
~~^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:323:9: error: no member named 'islessequal' in the global namespace
using ::islessequal;
~~^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/../sysroot/usr/include/c++/v1/cmath:324:9: error: no member named 'islessgreater' in the global namespace
using ::islessgreater;
~~^
@endcode
@m_class{m-noindent}
Last NDK version that's known to be reliably working with CMake is r17, newer it might be due to `&lt;ndk&gt;/sysroot/usr/include` being present in your
versions suffer from various issues due to changes introduced in NDK internals. include path. For some reason the NDK has two copies of system includes, one in
No work has been done yet on Magnum side to counter / work around those issues, `&lt;ndk&gt;/toolchains/llvm/prebuilt/&lt;host&gt;/sysroot/usr` and one here,
optimistically waiting on CMake devs to figure it out instead. See and the one in `&lt;ndk&gt;/sysroot` causes the above errors. Find the
[mosra/magnum#310](https://github.com/mosra/magnum/issues/310) for details. offending include dir and point it to the other location to fix the error.
@subsection platforms-android-troubleshooting-windows-nsight CMake complaining about some NVIDIA Nsight Tegra Visual Studio Edition on Windows @subsection platforms-android-troubleshooting-windows-nsight CMake complaining about some NVIDIA Nsight Tegra Visual Studio Edition on Windows

11
package/archlinux/PKGBUILD-android-arm64

@ -19,19 +19,20 @@ build() {
cmake .. \ cmake .. \
-DCMAKE_SYSTEM_NAME=Android \ -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=22 \ -DCMAKE_SYSTEM_VERSION=24 \
-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_ANDROID_STL_TYPE=c++_static \
-DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \
-G Ninja -G Ninja
fi fi
cd "$_rootdir/build-android-arm64" cd "$_rootdir/build-android-arm64"
cmake .. \ cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-22/arch-arm64/usr \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \
-DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/sysroot/usr \ -DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \
-DWITH_ANYAUDIOIMPORTER=OFF \ -DWITH_ANYAUDIOIMPORTER=OFF \
-DWITH_ANYIMAGECONVERTER=ON \ -DWITH_ANYIMAGECONVERTER=ON \
-DWITH_ANYIMAGEIMPORTER=ON \ -DWITH_ANYIMAGEIMPORTER=ON \
@ -55,3 +56,5 @@ package() {
cd "$_rootdir/build-android-arm64" cd "$_rootdir/build-android-arm64"
DESTDIR="$pkgdir/" ninja install/strip DESTDIR="$pkgdir/" ninja install/strip
} }
# kate: hl bash

Loading…
Cancel
Save