Skip to content

Instantly share code, notes, and snippets.

@gauravssnl
Last active November 16, 2024 12:47
Show Gist options
  • Save gauravssnl/44173389b662f654721eba704c998389 to your computer and use it in GitHub Desktop.
Save gauravssnl/44173389b662f654721eba704c998389 to your computer and use it in GitHub Desktop.
Cross compile Rust code for Android OS multiple architectures
export NDK_HOME_TOOLCHAIN_BIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/aarch64-linux-android30-clang" cargo build --target aarch64-linux-android
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/armv7a-linux-androideabi30-clang" cargo build --target armv7-linux-androideabi
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/x86_64-linux-android30-clang" cargo build --target x86_64-linux-android
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/i686-linux-android30-clang" cargo build --target i686-linux-android
export NDK_HOME_TOOLCHAIN_BIN="$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
cargo clean
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/aarch64-linux-android30-clang" cargo build --release --target aarch64-linux-android
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/armv7a-linux-androideabi30-clang" cargo build --release --target armv7-linux-androideabi
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/x86_64-linux-android30-clang" cargo build --release --target x86_64-linux-android
RUSTFLAGS="-C linker=${NDK_HOME_TOOLCHAIN_BIN}/i686-linux-android30-clang" cargo build --release --target i686-linux-android
ANDROID_TARGET_DIR=target/android
TARGET_FILE_NAME=hello
mkdir -p $ANDROID_TARGET_DIR/arm64-v8a/ && cp target/aarch64-linux-android/release/$TARGET_FILE_NAME $ANDROID_TARGET_DIR/arm64-v8a/$TARGET_FILE_NAME
mkdir -p $ANDROID_TARGET_DIR/armeabi-v7a/ && cp target/armv7-linux-androideabi/release/$TARGET_FILE_NAME $ANDROID_TARGET_DIR/armeabi-v7a/$TARGET_FILE_NAME
mkdir -p $ANDROID_TARGET_DIR/x86-64/ && cp target/x86_64-linux-android/release/$TARGET_FILE_NAME $ANDROID_TARGET_DIR/x86-64/$TARGET_FILE_NAME
mkdir -p $ANDROID_TARGET_DIR/x86/ && cp target/i686-linux-android/release/$TARGET_FILE_NAME $ANDROID_TARGET_DIR/x86/$TARGET_FILE_NAME
# ~/.cargo/config.toml
# target-applies-to-host = false
[target.aarch64-linux-android]
linker = "/home/gauravssnl/Android/Sdk/ndk/28.0.12433566/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang"
[target.armv7-linux-androideabi]
linker = "/home/gauravssnl/Android/Sdk/ndk/28.0.12433566/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi30-clang"
[target.i686-linux-android]
linker = "/home/gauravssnl/Android/Sdk/ndk/28.0.12433566/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android30-clang"
[target.x86_64-linux-android]
linker = "/home/gauravssnl/Android/Sdk/ndk/28.0.12433566/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android30-clang"
TARGET_FILE=hello
ANDROID_TARGET_DIR=target/android
ADB_FOLDER_NAME=gauravssnl
PHONE_TARGET_DIR=/data/adb/$ADB_FOLDER_NAME/
PHONE_TARGET_FILE=$PHONE_TARGET_DIR/$TARGET_FILE
PHONE_TEMP_FILE=/sdcard/$TARGET_FILE
echo "Executing commands on Android phone via ADB"
adb devices -l
echo "Reading device ABI"
ABI=$(adb shell getprop ro.product.cpu.abi)
echo "Device ABI : $ABI"
echo "Pushing the files to $PHONE_TARGET_DIR"
adb shell "su -c 'mkdir $PHONE_TARGET_DIR'"
adb push $ANDROID_TARGET_DIR/$ABI/$TARGET_FILE $PHONE_TEMP_FILE
adb shell "su -c 'mv $PHONE_TEMP_FILE $PHONE_TARGET_DIR'"
adb shell "su -c 'chmod a+x $PHONE_TARGET_FILE && $PHONE_TARGET_FILE'"
  1. Install Android SDK & NDK. Set Up ANDROID_HOME & NDK_HOME environment variables.
  2. We need to use nightly Rust & add targest related to Android. Run the below comamnds :
rustup target add armv7-linux-androideabi   # for arm
rustup target add i686-linux-android        # for x86
rustup target add aarch64-linux-android     # for arm64
rustup target add x86_64-linux-android      # for x86_64

rustup override set nightly

Now, we can follow miltiple ways to cross compile Rust code for Android OS.

a. Use cargo-ndk : https://github.com/bbqsrc/cargo-ndk ( simple & easy)

b. Use Mozilla gradle plugin(suitable for Android project) : https://github.com/mozilla/rust-android-gradle

c. Add the target linker paths for targets in ~/.cargo/config.toml. (Easiest way for anyone; now we need to configure anything in actual project config). Now, we can compile programs directl with cargo , Example :

cargo build --target aarch64-linux-android  --target armv7-linux-androideabi --target x86_64-linux-android --target i686-linux-android --target x86_64-unknown-linux-gnu

I found this step easier and simpler as we need not install anything for this and only one time config step is needed.

d. Use build.sh script in each project as provided above.

References : https://gendignoux.com/blog/2022/10/24/rust-library-android.html

https://github.com/bbqsrc/cargo-ndk

https://maciejglowka.com/blog/building-games-for-android-with-rust/

https://github.com/mozilla/rust-android-gradle

https://medium.com/@1ok1/android-rust-ndk-starter-dfb6f739ceed

https://www.reddit.com/r/rust/comments/16ngvhx/how_to_contol_the_link_stage_of_rust_build_system/

https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#target-applies-to-host

rust-lang/cargo#1109

There were many others pages which I read.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment