Using Android Studio 2.2 and higher, you can use the NDK and CMake to compile C and C++ code into a native library. Android Studio then packages your library into your APK using Gradle, the IDE's integrated build system.
If you are new to using CMake with Android Studio, go to Add C and C++ Code to Your Project to learn the basics of adding native sources to your project, creating a CMake build script, and adding your CMake project as a Gradle dependency. This page provides some additional information you can use to customize your CMake build.
Using CMake variables in Gradle
Once you link Gradle to your CMake project, you can configure certain NDK-specific variables that change the way CMake builds your native libraries. To pass an argument to CMake from your module-level build.gradle
file, use the following DSL:
android { ... defaultConfig { ... // This block is different from the one you use to link Gradle // to your CMake build script. externalNativeBuild { cmake { ... // Use the following syntax when passing arguments to variables: // arguments "-DVAR_NAME=ARGUMENT". arguments "-DANDROID_ARM_NEON=TRUE", // If you're passing multiple arguments to a variable, pass them together: // arguments "-DVAR_NAME=ARG_1 ARG_2" // The following line passes 'rtti' and 'exceptions' to 'ANDROID_CPP_FEATURES'. "-DANDROID_CPP_FEATURES=rtti exceptions" } } } buildTypes {...} // Use this block to link Gradle to your CMake build script. externalNativeBuild { cmake {...} } }
The following table describes some of the variables you can configure when using CMake with the NDK.
Variable name | Arguments | Description |
---|---|---|
ANDROID_TOOLCHAIN |
| Specifies the compiler toolchain CMake should use. |
ANDROID_PLATFORM | For a complete list of platform names and corresponding Android system images, see Android NDK Native APIs. | Specifies the name of the target Android platform. For example, Instead of changing this flag directly, you should set the
|
ANDROID_STL | For a complete list of options, see Helper Runtimes By default, CMake uses | Specifies the STL CMake should use. |
ANDROID_PIE |
| Specifies whether to use position-independent executables (PIE). Android's dynamic linker supports PIE on Android 4.1 (API level 16) and higher. |
ANDROID_CPP_FEATURES | This variable is empty by default. However, the following are a few examples of arguments you can pass:
| Specifies certain C++ features CMake needs to use when compiling your native library, such as RTTI (RunTime Type Information) and C++ exceptions. |
ANDROID_ALLOW_UNDEFINED_SYMBOLS |
| Specifies whether to throw an undefined symbol error if CMake encounters an undefined reference while building your native library. To disable these types of errors, set this variable to |
ANDROID_ARM_MODE |
| Specifies whether to generate ARM target binaries in |
ANDROID_ARM_NEON |
| Specifies whether CMake should build your native library with NEON support. |
ANDROID_DISABLE_NO_EXECUTE |
| Specifies whether to enable NX bit, or No eXecute, security feature. To disable this feature, pass |
ANDROID_DISABLE_RELRO |
| Specifies whether to enable read-only relocations. |
ANDROID_DISABLE_FORMAT_STRING_CHECKS |
| Specifies whether to compile your source code with format string protection. When enabled, the compiler throws an error if a non-constant format string is used in a |
Understanding the CMake build command
When debugging CMake build issues, it's helpful to know the specific build arguments that Android Studio uses when cross-compiling for Android.
Android Studio saves the build arguments it uses for executing a CMake build, in a cmake_build_command.txt
file. For each Application Binary Interface (ABI) that your app targets, and each build type for those ABIs (namely, release or debug), Android Studio generates a copy of the cmake_build_command.txt
file for that specific configuration. Android Studio then places the files it generates in the following directories:
<project-root>/<module-root>/.externalNativeBuild/cmake/<build-type>/<ABI>/
Tip: In Android Studio, you can quickly view these files by using the search keyboard shortcut (shift+shift
) and entering cmake_build_command.txtin the input field.
The following snippet shows an example of the CMake arguments to build a debuggable release of the hello-jni
sample targeting the armeabi-v7a
architecture.
Executable : /usr/local/google/home/{$USER}/Android/Sdk/cmake/3.6.3155560/bin/cmake arguments : -H/usr/local/google/home/{$USER}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/src/main/cpp -B/usr/local/google/home/{$USER}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/.externalNativeBuild/cmake/arm7Debug/armeabi-v7a -GAndroid Gradle - Ninja -DANDROID_ABI=armeabi-v7a -DANDROID_NDK=/usr/local/google/home/{$USER}/Android/Sdk/ndk-bundle -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/usr/local/google/home/{$USER}/Dev/github-projects/googlesamples/android-ndk/hello-jni/app/build/intermediates/cmake/arm7/debug/obj/armeabi-v7a -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=/usr/local/google/home/{$USER}/Android/Sdk/cmake/3.6.3155560/bin/ninja -DCMAKE_TOOLCHAIN_FILE=/usr/local/google/home/{$USER}/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=23 -DANDROID_TOOLCHAIN=clang jvmArgs :
Build arguments
The following table highlights the key CMake build arguments for Android. These build arguments are not meant to be set by developers. Instead, theAndroid Plugin for Gradle sets these arguments based on the build.gradle
configuration in your project.
Build Arguments | Description |
-G <build-system> | Type of build files that CMake generates. For projects in Android Studio with native code, the |
-DANDROID_ABI <abi> | The target ABI. The NDK supports a set of ABIs, as described in ABI Management. This option is similar to the By default, Gradle builds your native library into separate If the target ABI is not specified, CMake defaults to using Valid target names are:
|
-DANDROID_NDK <path> | Absolute path to the root directory of the NDK installation on your host. |
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY <path> | Location on your host where CMake puts the LIBRARY target files when built. |
-DCMAKE_BUILD_TYPE <type> | Similar to the build types for the ndk-build tool. The valid values are Release and Debug . To simplify debugging, CMake does not strip the release or debug version as part of the build. However, Gradle strips binaries when it packages them in the APK. |
-DCMAKE_MAKE_PROGRAM <program-name> | Tool to launch the native build system. The Gradle plugin sets this value to the CMake ninja generator bundled with the Android SDK. |
-DCMAKE_TOOLCHAIN_FILE <path> | Path to the android.toolchain.cmake file that CMake uses for cross-compiling for Android. Typically, this file is located in the $NDK/build/cmake/ directory, where $NDK is the NDK installation directory on your host. For more information about the toolchain file, see Cross Compiling for Android. |
-DANDROID_NATIVE_API_LEVEL <level> | Android API level that CMake compiles for. |
-DANDROID_TOOLCHAIN <type> | The compiler toolchain that CMake uses. Defaults to clang |
YASM support in CMake
NDK r15 and higher provides CMake support for building assembly code written in YASM to run on x86 and x86-64 architectures. YASM is an open-source assembler for x86 and x86-64 architectures, based on the NASM assembler.
You may find it useful to link assembly language programs or routines with C code in order to access C libraries or functions from your assembly code. You can also include short assembly routines in your compiled C code to take advantage of the better machine performance that assembly code affords.
To build assembly code with CMake, make the following changes in your project's CMakeLists.txt
:
- Call
enable_language
with the value set toASM_NASM
. - Depending on whether you are building a shared library or an executable binary, call
add_library
oradd_executable
. In the arguments, pass in a list of source files consisting of the.asm
files for the assembly program in YASM and and the.c
files for the associated C libraries or functions.
The following snippet shows how you might configure your CMakeLists.txt
to build a YASM program as a shared library.
cmake_minimum_required(VERSION 3.6.0) enable_language(ASM_NASM) add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
For an example of how to build a YASM program as an executable, see the test-yasm
code in the NDK git repository.
Reporting problems
If you run into any issues that aren't due to the open source version of CMake, report them via the android-ndk/ndk
issue tracker on GitHub.