Description
Following up on #1487, this bug outlines the work we'd need to do to support Rust in apps.
This is not being worked on, nor is it planned. This bug documents the work that needs to be done if that changes. Use the subscribe button on the right side of the page to be notified of updates.
Toolchain support
We need to get Rust to promote Android to Tier 1. Android is currently Tier 2, which means that it is guaranteed to build, but what's built is not guaranteed to work.
- Rust CI for testing android targets. Because all existing Tier 1 targets are able to self-host, Rust's CI likely does not include cross-testing support. We'd either need to enable self-hosting for rustc/cargo/etc on Android, or would need to build that cross-testing support. The former might be easier but the latter more accurately reflects the developer workflow.
- Provide test devices or adequate emulators
- Fix tests that have already regressed
- Commit to maintaining Android support upstream
- Distribute a prebuilt toolchain as a package in the Android SDK (this would not be the only nor even the recommended way to use rust, tier 1 support means you can just go use rustup, but we need SDK packages for AGP/AS integration)
Android APIs
We need to support the maintenance of the ndk-sys crate. This is the Rust equivalent of the NDK's sysroot. It provides definitions for all the platform APIs.
- Auto-generate this crate as part of the Android platform release process
Rust changes
I'm probably wrong about some of the current state here. Will update once Cunningham's Law kicks in.
- rustc needs to be taught about
minSdkVersion
. All Android code is currently built for the minimum API level supported by rustc. - Need a way to write things like
#if __ANDROID_MIN_SDK_VERSION__ >= 21
. aiui Rust's#cfg
doesn't support integer inequalities. - Need to support using APIs via weak symbols when the API is not available in the app's
minSdkVersion
. This also means diagnostics to protect users from calling weak APIs unguarded. - Compiler changes for
minSdkVersion
dependent binary features (gnu hashes, relocation packing, etc)
Build support in AGP
Take this section with a big grain of salt. I do not work on the IDE or AGP. That team might think of things I haven't.
- Integration with AGP
This is the least clear part of the roadmap. There are some existing tools in the rust ecosystem for this. We might be able to reuse those, but there is probably still some integration work required to smooth out that workflow.
This might be a cargo backend for externalNativeBuild
, a gradle DSL for rust, or a workflow for integrating rust into android apps that keeps cargo as a separate workflow. Possibly all three.
Steps most likely required regardless of the approach taken:
- Integration with SDK packaged rust toolchains
- Support for using arbitrary toolchains from rustup
- Support for pulling dependencies from crates.io
- Support for publishing AARs
- Cooperation with Android Studio's gradle sync phase (needs to introspect on build configuration without requiring a full build; most build systems are not cooperative with introspection)
- Integration with Java and C++ code
- Support for tools like bindgen
- Build caching
That last one (build caching) has been a major stumbling block for C++, FWIW. The gradle build cache cannot really support anything built by a subordinate build system (I have never met a build system that behaves well in a multi-build system environment), so this likely requires a gradle DSL for Rust, or a separate caching system for Rust.
Android Studio support
CLion already supports Rust, so a lot of this might Just Work, but we need to verify that. Some of these features do overlap with AGP support.
Take this section with a big grain of salt. I do not work on the IDE or AGP. That team might think of things I haven't.
- Basic editing features (make sure all the standard CLion features work for Android targets)
- Android extensions for clion (JNI inspections, for example) probably need to be reworked for rust
- Test support
- Profiling support
- Coverage support
- Code completion and documentation
Ecosystem support
- Identify essential crates, support them so Android is a maintained target. Anything that uses the cc crate or a build.rs is likely to be a fair amount of work
- Need commonly available test infrastructure so that projects can check Android in CI
- Crates that handle file systems, SSL certificates, audio, etc might need porting to work with Android's systems
- Crash handling support in Play (the tombstone will already be captured, but symbolization probably needs work)
Non-goals
Rust in the NDK
This comes up a lot. What "Rust in the NDK" actually means is "clang and rustc should couple their release cycles and come from the same zip file." I don't think anyone actually wants that. The NDK is already a large package, and there's little value in making Rust-only developers download Clang, or C++-only developers download Rust.
There's probably little value to getting rustc from Google in the first place. Once Android is a Tier 1 target, it's probably easier for everyone to just get the toolchain straight from rustup
. You'll have access to new releases much quicker that way, and you can use the same process for every platform you support rather than needing to handle Android differently.
There is one edge case where it would be valuable to have Clang and Rust coupled: cross-language LTO. Rust and Clang must use the same version of LLVM for that to work, so to support that we'll likely ship a Google-built rustc that aligns with the NDK's LTS Clang.
A parallel Android Framework for Rust
Just as with C/C++, there will be no "pure" Rust apps. Rust apps will be a zygote process that loads a native library via System.loadLibrary
. A large portion of Android itself is written in Java, so any native code in an app must transit JNI to access those parts of the system. Rust apps will have access to the same set of APIs as C/C++ do via the NDK. All APIs not exposed to the NDK must be called via JNI.