One more plugin to build Rust for Android
Tags: rust, android, cargo, ndk
Published: 2019-11-24 14:40:59

There are already several good articles on how to develop on Rust for Android: [Building and Deploying a Rust library on Android](https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-21-rust-on-android.html) by Mozilla, and [Rust once and share it with Android, iOS, and Flutter](https://dev.to/robertohuertasm/rust-once-and-share-it-with-android-ios-and-flutter-286o) by Roberto Huertas.

However, they describe how to build Rust manually (from the command line). That might be not the most convenient way to do it, since it makes the whole compilation and installing a several step process. I would prefer if Rust compilation was done automatically by `gradle`.

As it happens there is already such plugin: [Rust Android Gradle](https://github.com/mozilla/rust-android-gradle) by Mozilla. It is very good, but it misses one thing - it doesn't allow you to configure different compilation options for different gradle `buildType`s. For me it is crucial, so I decided to write my own plugin.

Here it is [Cargo NDK for Android projects](https://github.com/willir/cargo-ndk-android-gradle).

Let's see how you can use it. I won't spend much time talking about details that were already covered in the article above. I will only cover the main plugin use cases in detail.

## Installing dependencies

I assume that the Rust compiler itself is installed.

To develop for Android you will need Android Studio. It can be downloaded from its official site: [Android Studio](https://developer.android.com/studio).

Also, I would suggest installing the Rust plugin: [IntelliJ Rust](https://intellij-rust.github.io/), [Toml](https://plugins.jetbrains.com/plugin/8195-toml/). Currently (to my opinion) it works better than `rls` + `vscode`.

Once Android Studio is installed you also need NDK. Here are official instructions on how to install NDK: [Install NDK](https://developer.android.com/studio/projects/install-ndk).

Next step is to add android targets for rust:

```bash
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
```

And to install `cargo-ndk`:

```bash
cargo install cargo-ndk
```

`cargo-ndk` automatically finds and sets all appropriate environment variables to build rust libraries for android. So we won't need to specify them manually in `~/.cargo/config` or somewhere else.

We also need to set the `NDK_HOME` environment variable, as [`cargo ndk`](https://github.com/bbqsrc/cargo-ndk#usage) describes it. On my Linux, it is: `$HOME/Android/Sdk/ndk-bundle`.

## Gradle Build Config

I'll assume that you already have a Rust code to build, so here I'll only cover the gradle config.

The plugin is published on the gradle repo, so its usage is more or less straight forward. First in `build.gradle` we add:

```groovy
buildscript {
    repositories {
        ...
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        ...
        classpath "gradle.plugin.com.github.willir.rust:plugin:0.1.1"
    }
}
```

And then in `app/build.gradle`:

```groovy
apply plugin: "com.github.willir.rust.cargo-ndk-android"
```

And that's it, now the rust library should compile along with the rest Android project.

By default `buildDebug` gradle task will build `dev` (`debug`) cargo profile, and `buildRelease` will build `release` cargo profile. It can be changed:

```groovy
cargoNdk {
    buildTypes {
        release {
            buildType = "release"
        }
        debug {
            buildType = "release"
        }
    }
}
```

Now, for both `buildType`s `release` profile is going to be built.

The full list of options can be found on the GitHub page: [All Options](https://github.com/willir/cargo-ndk-android-gradle#all-options). Any of those options can be overridden for a specific `buildType`. Let's talk about some features, that might be helpful during development.

## Specify target via gradle property

Sometimes, during development, you don't need to build for all targets (`arm`, `arm64`), since you only test on one specific phone, so you don't want to spend time waiting for unused targets to be built. In this case, you can specify gradle property `rust-target` to the target you're testing right now. E.g.: `gradle buildDebug -Prust-target=arm64`. If `rust-target` is present plugin will only build for that target.

## apiLevel

By default `apiLevel` equals the `android.defaultConfig.minSdkVersion`, as far as I can tell, it is the most sensible option. It can be overridden.

However, there is one catch - android supports 64-bit targets only since API `21`. So, for example, for API `19` you cannot build `arm64` and `x86_64`. It still makes sense to build `arm64` and `x86_64`, even if your `minSdkVersion` is 19, they won't work on Android 4.4, but on Android 5.0+ they will work, and that's a lot of phones. So if your apiLevel is `19`, and you build `arm64`, `x86_64` targets, the plugin automatically increases `apiLevel` to `21` for those targets.

-----------------

That is basically it, I would like if somebody finds this plugin helpful. If you find any bugs, please report them, I'll try to fix them as soon as possible.