aboutsummaryrefslogtreecommitdiffhomepage
path: root/site
diff options
context:
space:
mode:
authorGravatar jingwen <jingwen@google.com>2018-07-11 11:50:30 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-07-11 11:51:58 -0700
commite169b94ce9b0e964b8edd231ef7eb3bed1cd2ccf (patch)
treedd8246ed3a967f366412b9c153f9e7ca6563f550 /site
parent93adb10c639fe3b7e5bfb17802b13ea46379e56e (diff)
Documentation for Android NDK support with Bazel
Example workspace: https://github.com/bazelbuild/examples/pull/66/files RELNOTES: None. PiperOrigin-RevId: 204162234
Diffstat (limited to 'site')
-rw-r--r--site/assets/android_ndk.pngbin0 -> 81966 bytes
-rw-r--r--site/docs/android-ndk.md365
-rw-r--r--site/docs/bazel-and-android.md1
3 files changed, 366 insertions, 0 deletions
diff --git a/site/assets/android_ndk.png b/site/assets/android_ndk.png
new file mode 100644
index 0000000000..76b63cb365
--- /dev/null
+++ b/site/assets/android_ndk.png
Binary files differ
diff --git a/site/docs/android-ndk.md b/site/docs/android-ndk.md
new file mode 100644
index 0000000000..4c3f74a946
--- /dev/null
+++ b/site/docs/android-ndk.md
@@ -0,0 +1,365 @@
+---
+layout: documentation
+title: Using the Android Native Development Kit with Bazel
+---
+
+# Using the Android Native Development Kit with Bazel
+
+_If you're new to Bazel, please start with the [Building Android with
+Bazel](https://docs.bazel.build/versions/master/tutorial/android-app.html)
+tutorial._
+
+## Table of contents
+
+- [Overview](#overview)
+- [Prerequisites](#prerequisites)
+- [Quick start](#quick-start)
+- [Example setup](#example-setup)
+- [Configuring the STL](#configuring-the-stl)
+- [Configuring the target ABI](#configuring-the-target-abi)
+- [Selecting a C++ standard](#selecting-a-c-standard)
+- [How it works: introducing Android configuration transitions](#how-it-works-introducing-android-configuration-transitions)
+- [Building a `cc_library` for Android without using `android_binary`](#building-a-cclibrary-for-android-without-using-androidbinary)
+
+## 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
+
+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 on the `android_ndk_repository` rule, see its the [Build
+Encyclopedia
+entry](https://docs.bazel.build/versions/master/be/android.html#android_ndk_repository).
+
+## 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:
+
+<img src="/assets/android_ndk.png" alt="Build graph of Android project with cc_library dependencies" width="600px"/>
+
+To build the app, simply run:
+
+```
+$ 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:
+
+```
+$ 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-the-target-abi).
+
+## Example setup
+
+This example is available in the [Bazel examples
+repository](https://github.com/bazelbuild/examples/tree/master/android-ndk).
+
+In the `BUILD.bazel` file, we define three targets 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 STL
+
+To configure the C++ STL, use the flag `--android_crosstool_top`.
+
+```
+bazel build //:app --android_crosstool_top=<target label>
+```
+
+The available STLs in `@androidndk` are:
+
+| STL | Target label |
+|---------|-----------------------------------------|
+| STLport | `@androidndk//:toolchain-stlport` |
+| libc++ | `@androidndk//:toolchain-libcpp` |
+| gnustl | `@androidndk//:toolchain-gnu-libstdcpp` |
+
+For r16 and below, the default STL is `gnustl`. For r17 and above, it is
+`libc++`. For convenience, the target `@androidndk//:default_crosstool` is
+aliased to the respective default STLs.
+
+Please note that from r18 onwards, [STLport and gnustl will be
+removed](https://android.googlesource.com/platform/ndk/+/master/docs/Roadmap.md#ndk-r18),
+making `libc++` the only STL in the NDK.
+
+See the [NDK
+documentation](https://developer.android.com/ndk/guides/cpp-support) for more
+information on these STLs.
+
+## Configuring the target ABI
+
+To configure the target ABI, use the `--fat_apk_cpu` flag as follows:
+
+```
+bazel build //:app --fat_apk_cpu=<comma-separated list of ABIs>
+```
+
+By default, Bazel builds native Android code for `armeabi-v7a`. To build for x86
+(e.g. for emulators), pass `--fat_apk_cpu=x86`. To create a fat APK for multiple
+architectures, you can specify multiple CPUs: `--fat_apk_cpu=armeabi-v7a,x86`.
+
+If more than one ABI is specified, Bazel will build an APK containing a shared
+object for each ABI.
+
+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) 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
+
+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` |
+
+For example:
+
+```
+bazel build //:app --cxxopt=-std=c++11
+```
+
+Read more about passing compiler and linker flags with `--cxxopt`, `--copt`, and
+`--linkopt` in the [User
+Manual](https://docs.bazel.build/versions/master/user-manual.html#flag--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
+)
+```
+
+## How it works: introducing Android configuration transitions
+
+The `android_binary` rule can explicitly ask Bazel to build its dependencies in
+an Android-compatible configuration so that the Bazel build *just works* without
+any special flags, except for `--fat_apk_cpu` and `--android_crosstool_top` for
+ABI and STL configuration.
+
+Behind the scenes, this automatic configuration uses Android [configuration
+transitions](https://docs.bazel.build/versions/master/skylark/rules.html#configurations).
+
+A compatible rule, like `android_binary`, automatically changes the
+configuration of its dependencies to an Android configuration, so only
+Android-specific subtrees of the build are affected. Other parts of the build
+graph are processed using the top-level target configuration. It may even
+process a single target in both configurations, if there are paths through the
+build graph to support that.
+
+Once Bazel is in an Android-compatible configuration, either specified at the
+top level or due to a higher-level transition point, additional transition
+points encountered do not further modify the configuration.
+
+The only built-in location that triggers the transition to the Android
+configuration is `android_binary`'s `deps` attribute.
+
+**Note:** The `data` attribute of `android_binary` intentionally does *not*
+trigger the transition. Additionally, `android_local_test` and `android_library`
+intentionally do *not* trigger the transition at all.
+
+For example, if you try to build an `android_library` target with a `cc_library`
+dependency without any flags, you may encounter an error about a missing JNI
+header:
+
+```
+ERROR: <project>/app/src/main/BUILD.bazel:16:1: C++ compilation of rule '//app/src/main:jni_lib' failed (Exit 1)
+app/src/main/cpp/native-lib.cpp:1:10: fatal error: 'jni.h' file not found
+#include <jni.h>
+ ^~~~~~~
+1 error generated.
+Target //app/src/main:lib failed to build
+Use --verbose_failures to see the command lines of failed build steps.
+```
+
+Ideally, these automatic transitions should make Bazel do the right thing in the
+majority of cases. However, if the target on the Bazel command-line is already
+below any of these transition rules, such as C++ developers testing a specific
+`cc_library`, then a custom `--crosstool_top` must be used.
+
+## 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 `--crosstool_top`, `--cpu` and `--host_crosstool_top`
+flags.
+
+For example:
+
+```shell
+bazel build //my/cc/jni:target \
+ --crosstool_top=@androidndk//:default_crosstool \
+ --cpu=<abi> \
+ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
+```
+
+Here, we specify that top-level `cc_library` and `cc_binary` targets are built
+using the NDK toolchain. However, this causes Bazel's own host tools to be built
+with the NDK toolchain (and thus for Android), because the host toolchain is
+copied from the target toolchain. To work around this, we specify the value of
+`--host_crosstool_top` to be `@bazel_tools//tools/cpp:toolchain` to explicitly
+set the host's C++ toolchain.
+
+With this approach, the entire build tree is affected.
+
+Note that 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](https://docs.bazel.build/versions/master/command-line-reference.html#target-pattern-syntax)
+like `/...` and `:all`.
+
+These flags can be put into a `bazelrc` config (one for each ABI), in
+`<project>/.bazelrc`:
+
+```
+common:android_x86 --crosstool_top=@androidndk//:default_crosstool
+common:android_x86 --cpu=x86
+common:android_x86 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
+
+common:android_armeabi-v7a --crosstool_top=@androidndk//:default_crosstool
+common:android_armeabi-v7a --cpu=armeabi-v7a
+common:android_armeabi-v7a --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
+
+# In general
+common:android_<abi> --crosstool_top=@androidndk//:default_crosstool
+common:android_<abi> --cpu=<abi>
+common:android_<abi> --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
+```
+
+Then, to build a `cc_library` for `x86_64` for example, run:
+
+```shell
+bazel build //my/cc/jni:target --config=android_x86_64
+```
+
+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.
diff --git a/site/docs/bazel-and-android.md b/site/docs/bazel-and-android.md
index 8327efcbd2..1e05344cc1 100644
--- a/site/docs/bazel-and-android.md
+++ b/site/docs/bazel-and-android.md
@@ -26,6 +26,7 @@ The following resources will help you work with Bazel on Android projects:
Android Studio using the [Android Studio with Bazel](https://ij.bazel.build/)
plugin.
* Bazel supports [Android instrumentation testing](https://docs.bazel.build/versions/master/android-instrumentation-test.html).
+* Learn how to use the [Android NDK with Bazel](https://docs.bazel.build/versions/master/android-ndk.html).
* Learn [How Android Builds Work in Bazel](https://blog.bazel.build/2018/02/14/how-android-builds-work-in-bazel.html).
## Android and new rules