Rust on Android Today?

Hi all,

I have a general help question about targeting Android.

I've seen a few comments in this forum but they are often several years old or refer to crates that are no longer maintained.

So, if you are going to build some logic in Rust that you want to run on Android (let's leave UI out of it for simplicity's sake), what would you do? Is it just a matter of adjusting your target architecture? Do you generally output a .so and link it in using JNI?

1 Like

Yes. You output a shared library that you use with JNI.

Rustup will allow you to add the common Android targets, but you'll still need to use a linker that works with Android. When rust asks for a linker, it really wants gcc. On Linux there's generally no problem, but on MacOS the default build system is clang and it doesn't work. The Android build system includes a version of gcc you can use on MacOS as a rust linker, but it isn't the default in the latest NDK.

Mozilla's article is still relevant today: Building and Deploying a Rust library on Android

2 Likes

here still mantained crate with android example: https://github.com/Dushistov/rust_swig/tree/master/android-example

Thanks, but for my use cases I'm looking for more like @fstephany's suggestion than a swig-based bindgen type solution. I want to target the Android device directly as opposed to FFI.

1 Like

Pretty much everything is using some JNI. The question is really how thick that layer is, and whether you have to think about it. Both 'cargo apk' and the android SDL2 port use JNI with a thin Java wrapper they've written. They pump through events and get a graphics context you can draw on from native code.

1 Like

Yeah, I figured that. I have no problem bundling my public API as a shared lib and just calling that from JNI as needed on my devices. Thanks, all for the advice! :pray:

One thing I'll add from recent experience (although grain of salt, our app is stuck on ndk r10e for the time being) -- backtrace-sys, openssl-sys, and a few other crates were pretty gnarly to convince to build using the old NDK toolchains -- I'm assuming it's easier on newer ones with CMake, but passing all of the correct configuration wasn't very straightforward in my case. I based our integration heavily on Lliwynd: Rust for Android games using SDL2, with some changes.

Overall, though, there are a few things I learned that might prove useful to others:

  • CARGO_TARGET_I686_LINUX_ANDROID_LINKER=... is much more version-control-friendly than .cargo/config values, at least for us (we have scripts to populate the correct env vars with absolute paths per dev machine, rather than everyone having to do it themselves)
  • piggybacking on the android cross-compilation configuration was the only reliable way I found for being able to correctly configure & build a number of crates which build their own C or C++ code
  • NDK libs and host-machine unit tests (think robolectric) are a bit rough. I used conditional compilation to separate out the JNI interface from Android-specific interfaces (logging right now) so that I can compile for the host OS and still include the JNI lib in unit tests
  • I am going to update our NDK soon, come hell or high water

I was planning to write a blog post whenever this actually ships, but I saw this here and thought a quick brain-dump might be helpful to someone passing through.

We have a slightly quirky monorepo setup, so some of the paths might be confusing, but here's a gist with the Android.mk and gradle changes I've used to make it work for our builds.

8 Likes

Thank you for sharing this level of detail, and especially the build configs. I will absolutely read and share that blog post when you have it!

https://github.com/sidneywang/rsbind

I have developed a tool to auto-generate binding codes between iOS/android and Rust.
Please check.

3 Likes

I have developed a tool to auto-generate binding codes between iOS/android and Rust.
Please check.

May be I missed something, but it looks like very similar to my project GitHub - Dushistov/flapigen-rs: Tool for connecting programs or libraries written in Rust with other languages , do you want cooperate?

@anp The gist link is broken, any chance you could update it?

We're doing things our own way in aw-android, which builds aw-server-rust as a shared lib and calls it from JNI. Works well, although our build process is a bit messy.

I've also tried getting Mozilla's rust-android-gradle to work, but for some reason some deps (openssl-sys) don't play nice with it, which is weird since I expect the process to be about the same.

You need feature=[vendored], because of Android NDK doesn't include openssl:

[target.'cfg(android)'.dependencies]
openssl-sys = { version = "0.9.55", features = ["vendored"]}

By the way, I recently updated my example: https://github.com/Dushistov/rust_swig/tree/master/android-example it should works with recent gradle/ndk/rustc and so on.
it now should works fine with

Oops! Must have accidentally included it in a cull of old gists. I emailed GitHub to see if they could restore it.