Awesome
cargo-ndk - Build Rust code for Android
<img alt="CI" src="https://github.com/bbqsrc/cargo-ndk/actions/workflows/ci.yml/badge.svg"> <img alt="Minimum supported Rust version: 1.73" src="https://img.shields.io/badge/MSRV-1.73-informational">
This cargo extension handles all the environment configuration needed for successfully building libraries
for Android from a Rust codebase, with support for generating the correct jniLibs
directory structure.
Installing
cargo install cargo-ndk
You'll also need to install all the toolchains you intend to use. Simplest way is with the following:
rustup target add \
aarch64-linux-android \
armv7-linux-androideabi \
x86_64-linux-android \
i686-linux-android
Modify as necessary for your use case.
Usage
If you have installed the NDK with Android Studio to its default location, cargo ndk
will automatically detect
the most recent NDK version and use it. This can be overriden by specifying the path to the NDK root directory in
the ANDROID_NDK_HOME
environment variable.
Examples
Building a library for 32-bit and 64-bit ARM systems
cargo ndk -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release
This specifies the Android targets to be built (ordinary triples are also supported), the output directory to use for placing the .so
files in the layout
expected by Android, and then the ordinary flags to be passed to cargo
.
Linking against and copying libc++_shared.so
into the relevant places in the output directory
Create a build.rs
in your project with the following:
use std::{env, path::{Path, PathBuf}};
fn main() {
if env::var("CARGO_CFG_TARGET_OS").unwrap() == "android" {
android();
}
}
fn android() {
println!("cargo:rustc-link-lib=c++_shared");
if let Ok(output_path) = env::var("CARGO_NDK_OUTPUT_PATH") {
let sysroot_libs_path =
PathBuf::from(env::var_os("CARGO_NDK_SYSROOT_LIBS_PATH").unwrap());
let lib_path = sysroot_libs_path.join("libc++_shared.so");
std::fs::copy(
lib_path,
Path::new(&output_path)
.join(&env::var("CARGO_NDK_ANDROID_TARGET").unwrap())
.join("libc++_shared.so"),
)
.unwrap();
}
}
Controlling verbosity
Add -v
or -vv
as you ordinarily would after the cargo command.
Providing environment variables for C dependencies
cargo-ndk
derives which environment variables to read the same way as the cc
crate.
cargo-ndk
-specific environment variables
These environment variables are exported for use in build scripts and other downstream use cases:
CARGO_NDK_ANDROID_PLATFORM
: the Android platform API number as an integer (e.g.21
)CARGO_NDK_ANDROID_TARGET
: the Android name for the build target (e.g.armeabi-v7a
)CARGO_NDK_OUTPUT_PATH
: the output path as specified with the-o
flagCARGO_NDK_SYSROOT_PATH
: path to the sysroot inside the Android NDKCARGO_NDK_SYSROOT_TARGET
: the target name for the files inside the sysroot (differs slightly from the standard LLVM triples)CARGO_NDK_SYSROOT_LIBS_PATH
: path to the libraries inside the sysroot with the given sysroot target (e.g.$CARGO_NDK_SYSROOT_PATH/usr/lib/$CARGO_NDK_SYSROOT_TARGET
)
Printing the environment
Sometimes you just want the environment variables that cargo-ndk
configures so you can, say, set up rust-analyzer in VS Code or similar.
If you want to source it into your bash environment:
source <(cargo ndk-env)
PowerShell:
cargo ndk-env --powershell | Out-String | Invoke-Expression
Rust Analyzer and anything else with JSON-based environment handling:
For configuring rust-analyzer, add the --json
flag and paste the blob into the relevant place in the config.
Supported hosts
- Linux
- macOS (
x86_64
andarm64
) - Windows
Local development
git clone
and then install the crate with cargo
:
cargo install --path .
Similar projects
- cargo-cocoapods - for building .a files for all Apple platforms, and bundling for CocoaPods
License
This project is licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.