---
title: 'Using the Android Native Development Kit with Bazel'
---

_If you're new to Bazel, please start with the [Building Android with
Bazel](/start/android-app ) tutorial._

## Overview {:#overview}

Bazel can run in many different build configurations, including several that use
the Android Native Development Kit (NDK) toolchain. This means that normal
`cc_library` and `cc_binary` rules can be compiled for Android directly within
Bazel. Bazel accomplishes this by using the `android_ndk_repository` repository
rule.

## Prerequisites {:#prerequisites}

Please ensure that you have installed the Android SDK and NDK.

To set up the SDK and NDK, add the following snippet to your `WORKSPACE`:

```python
android_sdk_repository(
    name = "androidsdk", # Required. Name *must* be "androidsdk".
    path = "/path/to/sdk", # Optional. Can be omitted if `ANDROID_HOME` environment variable is set.
)

android_ndk_repository(
    name = "androidndk", # Required. Name *must* be "androidndk".
    path = "/path/to/ndk", # Optional. Can be omitted if `ANDROID_NDK_HOME` environment variable is set.
)
```

For more information about the `android_ndk_repository` rule, see the [Build
Encyclopedia entry](/reference/be/android#android_ndk_repository).

If you're using a recent version of the Android NDK (r22 and beyond), use the
Starlark implementation of `android_ndk_repository`.
Follow the instructions in
[its README](https://github.com/bazelbuild/rules_android_ndk).

## Quick start {:#quick-start}

To build C++ for Android, simply add `cc_library` dependencies to your
`android_binary` or `android_library` rules.

For example, given the following `BUILD` file for an Android app:

```python
# In <project>/app/src/main/BUILD.bazel

cc_library(
    name = "jni_lib",
    srcs = ["cpp/native-lib.cpp"],
)

android_library(
    name = "lib",
    srcs = ["java/com/example/android/bazel/MainActivity.java"],
    resource_files = glob(["res/**/*"]),
    custom_package = "com.example.android.bazel",
    manifest = "LibraryManifest.xml",
    deps = [":jni_lib"],
)

android_binary(
    name = "app",
    deps = [":lib"],
    manifest = "AndroidManifest.xml",
)
```

This `BUILD` file results in the following target graph:

![Example results](/versions/8.4.0/docs/images/android_ndk.png "Build graph results")

**Figure 1.** Build graph of Android project with cc_library dependencies.

To build the app, simply run:

```posix-terminal
bazel build //app/src/main:app
```

The `bazel build` command compiles the Java files, Android resource files, and
`cc_library` rules, and packages everything into an APK:

```posix-terminal
$ zipinfo -1 bazel-bin/app/src/main/app.apk
nativedeps
lib/armeabi-v7a/libapp.so
classes.dex
AndroidManifest.xml
...
res/...
...
META-INF/CERT.SF
META-INF/CERT.RSA
META-INF/MANIFEST.MF
```

Bazel compiles all of the cc_libraries into a single shared object (`.so`) file,
targeted for the `armeabi-v7a` ABI by default. To change this or build for
multiple ABIs at the same time, see the section on [configuring the target
ABI](#configuring-target-abi).

## Example setup {:#example-setup}

This example is available in the [Bazel examples
repository](https://github.com/bazelbuild/examples/tree/master/android/ndk){: .external}.

In the `BUILD.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:

```c++
#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring

JNICALL
Java_com_example_android_bazel_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
```

The `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:

```java
public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("app");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       // ...
    }

    public native String stringFromJNI();

}
```

Note: The name of the native library is derived from the name of the top
level `android_binary` target. In this example, it is `app`.

## Configuring the target ABI {:#configuring-target-abi}

To configure the target ABI, use the `--android_platforms` flag as follows:

```posix-terminal
bazel build //:app --android_platforms={{ "<var>" }}comma-separated list of platforms{{ "</var>" }}
```

Just like the `--platforms` flag, the values passed to `--android_platforms` are
the labels of [`platform`](https://bazel.build/versions/8.4.0/reference/be/platforms-and-toolchains#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:

```py
platform(
    name = "android_arm64",
    constraint_values = [
        "@platforms//os:android",
        "@platforms//cpu:arm64",
    ],
)
```

Every Android `platform` should use the [`@platforms//os:android`](https://github.com/bazelbuild/platforms/blob/33a3b209f94856193266871b1545054afb90bb28/os/BUILD#L36)
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`

And, of course, for a multi-architecture APK, you pass multiple labels, for
example: `--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                        |

See [the NDK docs](https://developer.android.com/ndk/guides/abis.html){: .external}
for more information on these ABIs.

Multi-ABI Fat APKs are not recommended for release builds since they increase
the size of the APK, but can be useful for development and QA builds.

## Selecting a C++ standard {:#selecting-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`   |

For example:

```posix-terminal
bazel build //:app --cxxopt=-std=c++11
```

Read more about passing compiler and linker flags with `--cxxopt`, `--copt`, and
`--linkopt` in the [User Manual](/versions/8.4.0/docs/user-manual#cxxopt).

Compiler and linker flags can also be specified as attributes in `cc_library`
using `copts` and `linkopts`. For example:

```python
cc_library(
    name = "jni_lib",
    srcs = ["cpp/native-lib.cpp"],
    copts = ["-std=c++11"],
    linkopts = ["-ldl"], # link against libdl
)
```

## Building a `cc_library` for Android without using `android_binary` {:#cclibrary-android}

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`:

```posix-terminal
bazel build //my/cc/jni:target \
      --platforms=//my/platforms:x86_64
```

With this approach, the entire build tree is affected.

Note: All of the targets on the command line must be compatible with
building for Android when specifying these flags, which may make it difficult to
use [Bazel wild-cards](/versions/8.4.0/run/build#specifying-build-targets) like
`/...` and `:all`.

These flags can be put into a `bazelrc` config (one for each ABI), in
`{{ "<var>" }}project{{ "</var>" }}/.bazelrc`:

```
common:android_x86 --platforms=//my/platforms:x86

common:android_armeabi-v7a --platforms=//my/platforms:armeabi-v7a

# In general
common:android_<abi> --platforms=//my/platforms:<abi>
```

Then, to build a `cc_library` for `x86` for example, run:

```posix-terminal
bazel build //my/cc/jni:target --config=android_x86
```

In general, use this method for low-level targets (like `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.
