Compiling Rust Apps for Termux with nix-shell
2019-06-29I’ve been building a program to track how I spend my time, and a couple of the requirements are an interface on my phone, and sync between multiple devices. Since I haven’t built an android app in forever, I decided to target termux, at least initially. This will allow me to use the app and test out the synchronization protocol without a ton of upfront effort into building a graphical user interface.
Cross Compiling for termux
The first thing we need to cross compile to termux is a cross compiler. rustc is a cross compiler by default, but with some important caveats: rustc needs a linker and a pre-made rust stdlib for the target platform.
I use the wonderful NixOS as my dev environment, so we will be using nix-shell to get the dependencies we need. In your project’s directory, create an android.nix file and put the following code inside it.
# android.nix
let
# Get the mozilla nixpkg overlay for a convient rust installation
moz_overlay = import (
builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz
);
native-pkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
pkgs = import <nixpkgs> {
crossSystem = native-pkgs.lib.systems.examples.armv7a-android-prebuilt;
};
# Get the latest stable compiler version and install the armv7 android target with it
rust = (native-pkgs.rustChannels.stable.rust.override {
targets = [
"armv7-linux-androideabi"
];
});
in
# Note the call to `pkgs` here, instead of `native-pkgs`
pkgs.callPackage (
{mkShell, cargo}:
# mkShell will drop us into a shell that has a $CC for the target platform
mkShell {
nativeBuildInputs = [ rust ];
}
) {}
Running nix-shell android.nix will drop you into a shell with cargo and an armv7 c compiler. Before we can build the rust project, we have to inform cargo to use said compiler for linking armv7 executables. Open .cargo/config (in your project’s directory) and put the following in:
[target.armv7-linux-androideabi]
linker = "armv7a-unknown-linux-androideabi-clang"
Now we can build our project termux! We simply start nix-shell and then tell cargo to compile the project:
$ nix-shell android.nix --run "cargo build --target=armv7-linux-androideabi"
Now just push the executable to your android device.
$ adb push target/armv7-linux-androideabi/debug/cli /storage/self/primary/our-cli-app
And then run the app from termux.
$ cp /storage/self/primary/our-cli-app ./
$ chmod ./our-cli-app
$ ./our-cli-app --help
Resources
- https://nixos.wiki/wiki/Cross_Compiling
- https://matthewbauer.us/blog/beginners-guide-to-cross.html
- https://github.com/NixOS/nixpkgs/blob/master/lib/systems/examples.nix
- https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/androidndk-pkgs/androidndk-pkgs.nix
- https://github.com/NixOS/nixpkgs/pull/56540