xref: /OK3568_Linux_fs/external/mpp/build/android/README.md (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# android-cmake
2*4882a593Smuzhiyun
3*4882a593SmuzhiyunCMake 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 experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html
4*4882a593Smuzhiyun
5*4882a593SmuzhiyunMain goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android.
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun## TL;DR
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun    cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \
10*4882a593Smuzhiyun          -DANDROID_NDK=<ndk_path>                       \
11*4882a593Smuzhiyun          -DCMAKE_BUILD_TYPE=Release                     \
12*4882a593Smuzhiyun          -DANDROID_ABI="armeabi-v7a with NEON"          \
13*4882a593Smuzhiyun          <source_path>
14*4882a593Smuzhiyun    cmake --build .
15*4882a593Smuzhiyun
16*4882a593SmuzhiyunOne-liner:
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun    cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK=<ndk_path> -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" <source_path> && cmake --build .
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun_android-cmake_ will search for your NDK install in the following order:
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun1. Value of `ANDROID_NDK` CMake variable;
23*4882a593Smuzhiyun1. Value of `ANDROID_NDK` environment variable;
24*4882a593Smuzhiyun1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable;
25*4882a593Smuzhiyun1. Search platform specific locations (home folder, Windows "Program Files", etc).
26*4882a593Smuzhiyun
27*4882a593SmuzhiyunSo if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically.
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun## Getting started
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunTo build a cmake-based C/C++ project for Android you need:
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html
34*4882a593Smuzhiyun* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download
35*4882a593Smuzhiyun
36*4882a593SmuzhiyunThe _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with.
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun## Difference from traditional CMake
39*4882a593Smuzhiyun
40*4882a593SmuzhiyunFolowing the _ndk-build_ the _android-cmake_ supports **only two build targets**:
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun* `-DCMAKE_BUILD_TYPE=Release`
43*4882a593Smuzhiyun* `-DCMAKE_BUILD_TYPE=Debug`
44*4882a593Smuzhiyun
45*4882a593SmuzhiyunSo don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default.
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun## Difference from _ndk-build_
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun* Latest GCC available in NDK is used as the default compiler;
50*4882a593Smuzhiyun* `Release` builds with `-O3` instead of `-Os`;
51*4882a593Smuzhiyun* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target);
52*4882a593Smuzhiyun* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64;
53*4882a593Smuzhiyun* GCC's stack protector is not used neither in `Debug` nor `Release` configurations;
54*4882a593Smuzhiyun* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters);
55*4882a593Smuzhiyun* No file level Neon via `.neon` suffix;
56*4882a593Smuzhiyun
57*4882a593SmuzhiyunThe following features of _ndk-build_ are not supported by the _android-cmake_ yet:
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun* `armeabi-v7a-hard` ABI
60*4882a593Smuzhiyun* `libc++_static`/`libc++_shared` STL runtime
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun## Basic options
63*4882a593Smuzhiyun
64*4882a593SmuzhiyunSimilarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D<NAME>=<VALUE>` or as environment variables:
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations;
67*4882a593Smuzhiyun* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are:
68*4882a593Smuzhiyun    * `armeabi` - ARMv5TE based CPU with software floating point operations;
69*4882a593Smuzhiyun    * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16);
70*4882a593Smuzhiyun    * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit;
71*4882a593Smuzhiyun    * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit;
72*4882a593Smuzhiyun    * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP;
73*4882a593Smuzhiyun    * `x86` - IA-32 instruction set
74*4882a593Smuzhiyun    * `mips` - MIPS32 instruction set
75*4882a593Smuzhiyun    * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer
76*4882a593Smuzhiyun    * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer
77*4882a593Smuzhiyun    * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer
78*4882a593Smuzhiyun* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI:
79*4882a593Smuzhiyun    * `android-8` for ARM;
80*4882a593Smuzhiyun    * `android-9` for x86 and MIPS;
81*4882a593Smuzhiyun    * `android-21` for 64-bit ABIs.
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun    Building for `android-L` is possible only when it is explicitly selected.
84*4882a593Smuzhiyun* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`.
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun    Example values are:
87*4882a593Smuzhiyun    * `aarch64-linux-android-4.9`
88*4882a593Smuzhiyun    * `aarch64-linux-android-clang3.5`
89*4882a593Smuzhiyun    * `arm-linux-androideabi-4.8`
90*4882a593Smuzhiyun    * `arm-linux-androideabi-4.9`
91*4882a593Smuzhiyun    * `arm-linux-androideabi-clang3.5`
92*4882a593Smuzhiyun    * `mips64el-linux-android-4.9`
93*4882a593Smuzhiyun    * `mipsel-linux-android-4.8`
94*4882a593Smuzhiyun    * `x86-4.9`
95*4882a593Smuzhiyun    * `x86_64-4.9`
96*4882a593Smuzhiyun    * etc.
97*4882a593Smuzhiyun* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`.
98*4882a593Smuzhiyun    * `none` - do not configure the runtime.
99*4882a593Smuzhiyun    * `system` - use the default minimal system C++ runtime library.
100*4882a593Smuzhiyun        * Implies `-fno-rtti -fno-exceptions`.
101*4882a593Smuzhiyun    * `system_re` - use the default minimal system C++ runtime library.
102*4882a593Smuzhiyun        * Implies `-frtti -fexceptions`.
103*4882a593Smuzhiyun    * `gabi++_static` - use the GAbi++ runtime as a static library.
104*4882a593Smuzhiyun        * Implies `-frtti -fno-exceptions`.
105*4882a593Smuzhiyun        * Available for NDK r7 and newer.
106*4882a593Smuzhiyun    * `gabi++_shared` - use the GAbi++ runtime as a shared library.
107*4882a593Smuzhiyun        * Implies `-frtti -fno-exceptions`.
108*4882a593Smuzhiyun        * Available for NDK r7 and newer.
109*4882a593Smuzhiyun    * `stlport_static` - use the STLport runtime as a static library.
110*4882a593Smuzhiyun        * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
111*4882a593Smuzhiyun        * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
112*4882a593Smuzhiyun    * `stlport_shared` - use the STLport runtime as a shared library.
113*4882a593Smuzhiyun        * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
114*4882a593Smuzhiyun        * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
115*4882a593Smuzhiyun    * **`gnustl_static`** - use the GNU STL as a static library.
116*4882a593Smuzhiyun        * Implies `-frtti -fexceptions`.
117*4882a593Smuzhiyun    * `gnustl_shared` - use the GNU STL as a shared library.
118*4882a593Smuzhiyun        * Implies `-frtti -fno-exceptions`.
119*4882a593Smuzhiyun        * Available for NDK r7b and newer.
120*4882a593Smuzhiyun        * Silently degrades to `gnustl_static` if not available.
121*4882a593Smuzhiyun* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable.
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun## Advanced _android-cmake_ options
124*4882a593Smuzhiyun
125*4882a593SmuzhiyunNormally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues:
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`;
128*4882a593Smuzhiyun* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors;
129*4882a593Smuzhiyun* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries;
130*4882a593Smuzhiyun    * actually it is turned `ON` by default for NDK older than `r7`
131*4882a593Smuzhiyun* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime;
132*4882a593Smuzhiyun* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are:
133*4882a593Smuzhiyun    * `RELEASE` - public releases from Google;
134*4882a593Smuzhiyun    * `LINARO` - NDK from Linaro project;
135*4882a593Smuzhiyun    * `ANDROID` - NDK from AOSP.
136*4882a593Smuzhiyun* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`);
137*4882a593Smuzhiyun* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86);
138*4882a593Smuzhiyun* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`);
139*4882a593Smuzhiyun* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`);
140*4882a593Smuzhiyun* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product/<product_name>/obj/lib/libm.so`) to workaround unresolved `sincos`.
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun## Fine-tuning `CMakeLists.txt` for _android-cmake_
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun### Recognizing Android build
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff:
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun    if (ANDROID)
149*4882a593Smuzhiyun        message(STATUS "Hello from Android build!")
150*4882a593Smuzhiyun    endif()
151*4882a593Smuzhiyun
152*4882a593SmuzhiyunThe recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value:
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun* `armv5te` - for `armeabi` ABI
155*4882a593Smuzhiyun* `armv6` - for `armeabi-v6 with VFP` ABI
156*4882a593Smuzhiyun* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs
157*4882a593Smuzhiyun* `aarch64` - for `arm64-v8a` ABI
158*4882a593Smuzhiyun* `i686` - for `x86` ABI
159*4882a593Smuzhiyun* `x86_64` - for `x86_64` ABI
160*4882a593Smuzhiyun* `mips` - for `mips` ABI
161*4882a593Smuzhiyun* `mips64` - for `mips64` ABI
162*4882a593Smuzhiyun
163*4882a593SmuzhiyunOther variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are:
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun* `NEON` - set if target ABI supports Neon;
166*4882a593Smuzhiyun* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level)
167*4882a593Smuzhiyun* `ANDROID_NDK_RELEASE` - version of the Android NDK
168*4882a593Smuzhiyun* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform
169*4882a593Smuzhiyun* `ANDROID_RTTI` - set if rtti is enabled by the runtime
170*4882a593Smuzhiyun* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun### Finding packages
173*4882a593Smuzhiyun
174*4882a593SmuzhiyunWhen crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun    find_package(ZLIB)
177*4882a593Smuzhiyun
178*4882a593Smuzhiyunwill surely find libz.so within the Android NDK.
179*4882a593Smuzhiyun
180*4882a593SmuzhiyunHowever sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`:
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun    find_host_package(Doxygen)
183*4882a593Smuzhiyun    find_host_program(PDFLATEX pdflatex)
184*4882a593Smuzhiyun
185*4882a593SmuzhiyunHowever this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command):
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun    # Search packages for host system instead of packages for target system
188*4882a593Smuzhiyun    # in case of cross compilation these macro should be defined by toolchain file
189*4882a593Smuzhiyun    if(NOT COMMAND find_host_package)
190*4882a593Smuzhiyun      macro(find_host_package)
191*4882a593Smuzhiyun        find_package(${ARGN})
192*4882a593Smuzhiyun      endmacro()
193*4882a593Smuzhiyun    endif()
194*4882a593Smuzhiyun    if(NOT COMMAND find_host_program)
195*4882a593Smuzhiyun      macro(find_host_program)
196*4882a593Smuzhiyun        find_program(${ARGN})
197*4882a593Smuzhiyun      endmacro()
198*4882a593Smuzhiyun    endif()
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun### Compiler flags recycling
201*4882a593Smuzhiyun
202*4882a593SmuzhiyunMake sure to do the following in your scripts:
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}")
205*4882a593Smuzhiyun    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}")
206*4882a593Smuzhiyun
207*4882a593SmuzhiyunThe flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags.
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun## Troubleshooting
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun### Building on Windows
212*4882a593Smuzhiyun
213*4882a593SmuzhiyunFirst of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead.
214*4882a593Smuzhiyun
215*4882a593SmuzhiyunTo build with Ninja you need:
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun* Ensure you are using CMake newer than 2.8.9;
218*4882a593Smuzhiyun* Download the latest Ninja from https://github.com/martine/ninja/releases;
219*4882a593Smuzhiyun* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable);
220*4882a593Smuzhiyun* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`).
221*4882a593Smuzhiyun* Enjoy the fast native multithreaded build :)
222*4882a593Smuzhiyun
223*4882a593SmuzhiyunBut if you still want to stick to old make then:
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun* Get a Windows port of GNU Make:
226*4882a593Smuzhiyun    * Android NDK r7 (and newer) already has `make.exe` on board;
227*4882a593Smuzhiyun    * `mingw-make` should work as fine;
228*4882a593Smuzhiyun    * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm.
229*4882a593Smuzhiyun* Add path to your `make.exe` to system PATH or always use full path;
230*4882a593Smuzhiyun* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="<full/path/to/>make.exe"`
231*4882a593Smuzhiyun    * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make.
232*4882a593Smuzhiyun* Run `make.exe` or `cmake --build .` for single-threaded build.
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun### Projects with assembler files
235*4882a593Smuzhiyun
236*4882a593SmuzhiyunThe _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun## Copying
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause)