Overview
Bazel can run in many different build configurations, including several that use the Android Native Development Kit (NDK) toolchain. This means that normalcc_library and cc_binary rules can be compiled for Android directly within
Bazel. Bazel accomplishes this by using the android_ndk_repository repository
rule and its related bzlmod extension.
For general Android
compilation, use rules_android.
This tutorial demonstrates how to integrate C++ library dependencies into
Android apps and uses
rules_android_ndk for NDK
toolchain discovery and registration.
Prerequisites
Please ensure that you have installed the Android SDK and NDK.NDK and SDK setup
External repository setup varies depending on whether you are using WORKSPACE or bzlmod (MODULE.bazel). Bzlmod is the preferred solution for Bazel 7+. Note that the MODULE.bazel and WORKSPACE setup stanzas are independent of each other. If you are using one dependency management solution, you don’t need to add the boilerplate for the other.Bzlmod MODULE.bazel setup
Add the following snippet to your MODULE.bazel:Legacy WORKSPACE setup
Add the following snippet to yourWORKSPACE:
- Both
rules_androidandrules_android_ndkrules require extra boilerplate not depicted in the WORKSPACE snippet above. For an up-to-date and fully-formed instantiation stanza, see the WORKSPACE file ofrules_android_ndk’s basic example app.
android_ndk_repository rule, see its
docstring.
Quick start
To build C++ for Android, simply addcc_library dependencies to your
android_binary or android_library rules.
For example, given the following BUILD file for an Android app:
BUILD file results in the following target graph:
Figure 1. Build graph of Android project with cc_library dependencies.
To build the app, simply run:
--android_platforms, your build will fail with
errors about missing JNI headers.
The bazel build command compiles the Java files, Android resource files, and
cc_library rules, and packages everything into an APK:
.so) file,
targeted the architectures specified by --android_platforms.
See the section on configuring the target ABI for
more details.
Example setup
This example is available in the Bazel examples repository. In theBUILD.bazel file, three targets are defined with the android_binary,
android_library, and cc_library rules.
The android_binary top-level target builds the APK.
The cc_library target contains a single C++ source file with a JNI function
implementation:
android_library target specifies the Java sources, resource files, and the
dependency on a cc_library target. For this example, MainActivity.java loads
the shared object file libapp.so, and defines the method signature for the JNI
function:
android_binary target. In this example, it is app.
Configuring the target ABI
To configure the target ABI, use the--android_platforms flag as follows:
--platforms flag, the values passed to --android_platforms are
the labels of platform
targets, using standard constraint values to describe your device.
For example, for an Android device with a 64-bit ARM processor, you’d define
your platform like this:
platform should use the @platforms//os:android
OS constraint. To migrate the CPU constraint, check this chart:
| CPU Value | Platform |
|---|---|
armeabi-v7a | @platforms//cpu:armv7 |
arm64-v8a | @platforms//cpu:arm64 |
x86 | @platforms//cpu:x86_32 |
x86_64 | @platforms//cpu:x86_64 |
--android_platforms=//:arm64,//:x86_64 (assuming you defined those in
your top-level BUILD.bazel file).
Bazel is unable to select a default Android platform, so one must be defined and
specified with --android_platforms.
Depending on the NDK revision and Android API level, the following ABIs are
available:
| NDK revision | ABIs |
|---|---|
| 16 and lower | armeabi, armeabi-v7a, arm64-v8a, mips, mips64, x86, x86_64 |
| 17 and above | armeabi-v7a, arm64-v8a, x86, x86_64 |
Selecting a C++ standard
Use the following flags to build according to a C++ standard:| C++ Standard | Flag |
|---|---|
| C++98 | Default, no flag needed |
| C++11 | --cxxopt=-std=c++11 |
| C++14 | --cxxopt=-std=c++14 |
| C++17 | --cxxopt=-std=c++17 |
--cxxopt, --copt, and
--linkopt in the User Manual.
Compiler and linker flags can also be specified as attributes in cc_library
using copts and linkopts. For example:
Building a cc_library for Android without using android_binary
To build a standalone cc_binary or cc_library for Android without using an
android_binary, use the --platforms flag.
For example, assuming you have defined Android platforms in
my/platforms/BUILD:
/... and :all.
These flags can be put into a bazelrc config (one for each ABI), in
{{ "<var>" }}project{{ "</var>" }}/.bazelrc:
cc_library for x86 for example, run:
cc_library) or when
you know exactly what you’re building; rely on the automatic configuration
transitions from android_binary for high-level targets where you’re expecting
to build a lot of targets you don’t control.