Skip to content

Instantly share code, notes, and snippets.

@ignlg
Last active January 28, 2024 15:16
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ignlg/6b6fff6af53b628a1fa8410585fad627 to your computer and use it in GitHub Desktop.
Save ignlg/6b6fff6af53b628a1fa8410585fad627 to your computer and use it in GitHub Desktop.
How to build a rust project with nannou for Android on macOS

How to build a rust project with nannou for Android on macOS

This is a work in progress because I have not been able to build an apk yet, but I can build an Android executable.

I keep this notes for my future self and for you if you are fighting against this beast too.

Please read it all, because I will write down every do's and dont's that I have found.

I will polish the document as soon as I have everything.

Context: projects

A rust hello world project. This is the Cargo.toml:

[package]
name = "hello_world"
version = "0.1.0"
authors = ["Ignacio Lago <ignacio@ignaciolago.com>"]
edition = "2018"

[dependencies]

A rust + nannou project, nothing special about it. This is the Cargo.toml:

[package]
name = "synthwave84"
version = "0.1.0"
authors = ["Ignacio Lago <ignacio@ignaciolago.com>"]
edition = "2018"

[dependencies]
nannou = "0.12"

Compile an executable

The main tutorial is outdated: Building and Deploying a Rust library on Android

These are the current steps (as for Feb 2020):

Install Android Studio

Probably the easiest way to download the SDKs: Android Studio. If you are doing stuff for Android you would need it anyway.

Download Android SDK / NDK via Android Studio

Open Android Studio.

From the toolbar, go to

Android Studio > Preferences > Appearance & Behaviour > Android SDK > SDK Tools.

Check the following options for installation and click OK.

  • Android SDK Tools
  • NDK (Side by side)

These are my selected options:

Android Studio SDK options

Alternative: NDK direct download

Download the right SDK/NDK version for cargo apk : 18b

This is a spoiler, cargo-apk will need NDK 18b, the latest version to use gcc. From r19 it uses Cmake.

Links:

The error:
> cargo apk build

Compiling android_native_app_glue.c
error: could not execute process `/Users/ignlg/Library/Android/sdk/ndk/21.0.6113669/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc /Users/ignlg/Library/Android/sdk/ndk/21.0.6113669/sources/android/native_app_glue/android_native_app_glue.c -c -o /Users/ignlg/Development/rust/android-test/target/android-artifacts/arm-linux-androideabi/android_native_app_glue.o --sysroot /Users/ignlg/Library/Android/sdk/ndk/21.0.6113669/platforms/android-18/arch-arm` (never executed)

Caused by:
  No such file or directory (os error 2)

Look at the end of that command:

/Users/ignlg/Library/Android/sdk/ndk/21.0.6113669/platforms/android-18/arch-arm

You need android-18.

Some links about it:

The fix:

On the SDK Tools select Show Package Details and, under NDK (Side by side) select: 18.1.5063045

Package Details

Install CMake

Via Hombrew

brew install cmake

Note: I have not tested the alternative: Installing it with Android Studio.

Install OpenSSL

The OpenSSL version that comes with my macOS is:

> openssl version
LibreSSL 2.6.5
The error:
error: failed to run custom build command for `openssl v0.9.24`
process didn't exit successfully: `/build/rustup/src/rustup.rs-1.14.0/target/release/build/openssl-4e050bcc8f5aae18/build-script-build` (exit code: 101)
--- stderr
thread 'main' panicked at 'Unable to detect OpenSSL version', /build/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-0.9.24/build.rs:16:14
note: Run with `RUST_BACKTRACE=1` for a backtrace.

warning: build failed, waiting for other jobs to finish...
error: build failed
The fix:

Via Homebrew

brew install openssl

Configure your build environment (.bashrc, .zprofile, etc):

export OPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include
export OPENSSL_LIB_DIR=/usr/local/opt/openssl/lib

Setup NDK environment

Variables for NDK >= r19 (change 21.0.6113669 with your latest version):

export ANDROID_HOME=$HOME/Library/Android/sdk
export NDK_HOME=$ANDROID_HOME/ndk/21.0.6113669
export NDK_ROOT=$ANDROID_HOME/ndk/21.0.6113669

OR Variables for NDK r18:

export ANDROID_HOME=$HOME/Library/Android/sdk
export NDK_HOME=$ANDROID_HOME/ndk/18.1.5063045
export NDK_ROOT=$ANDROID_HOME/ndk/18.1.5063045

Note that the version used is 18.1.5063045 for cargo apk.

Setup cargo

The error (if you follow an outdated tutorial):

❯ ${NDK_HOME}/build/tools/make_standalone_toolchain.py --api 26 --arch arm64 --install-dir NDK/arm64
WARNING:__main__:make_standalone_toolchain.py is no longer necessary. The
$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin directory contains target-specific scripts that perform
the same task. For example, instead of:

    $ python $NDK/build/tools/make_standalone_toolchain.py \
        --arch arm64 --api 26 --install-dir toolchain
    $ toolchain/bin/clang++ src.cpp

Instead use:

    $ $NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android26-clang++ src.cpp

How it is done now

Modify or create $HOME/.cargo/config:

[target.aarch64-linux-android]
ar = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ar"
linker = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android29-clang"

[target.armv7-linux-androideabi]
ar = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-ar"
linker = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi29-clang"

[target.i686-linux-android]
ar = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-androideabi-ar"
linker = "Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-androideabi29-clang"

Note that the version used should be 18.1.5063045 for cargo apk.

Old method

mkdir ~/.NDK;

$NDK_HOME/build/tools/make_standalone_toolchain.py --api 26 --arch arm64 --install-dir ~/.NDK/arm64;
$NDK_HOME/build/tools/make_standalone_toolchain.py --api 26 --arch arm --install-dir ~/.NDK/arm;
$NDK_HOME/build/tools/make_standalone_toolchain.py --api 26 --arch x86 --install-dir ~/.NDK/x86;

Setup rust

rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android

Important note:

At this point, even using NDK 21.x, any of these commands should work:

cargo build --target aarch64-linux-android --release
cargo build --target armv7-linux-androideabi --release
cargo build --target i686-linux-android --release

If you receive an error mentioning cargo_apk_injected_glue_get_native_window then cargo-apk is needed.


Install cargo-apk

The error:

After executing:

> cargo build --release --all --target armv7-linux-androideabi
error: linking with `/Users/ignlg/Library/Android/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi29-clang` failed: exit code: 1

. . .

= note: /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:123: error: undefined reference to 'cargo_apk_injected_glue_get_native_window'
          /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:123: error: undefined reference to 'cargo_apk_injected_glue_get_native_window'
          /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:123: error: undefined reference to 'cargo_apk_injected_glue_get_native_window'
          /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:123: error: undefined reference to 'cargo_apk_injected_glue_get_native_window'
          /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:77: error: undefined reference to 'cargo_apk_injected_glue_add_sender'
          /Users/ignlg/.cargo/registry/src/github.com-1ecc6299db9ec823/android_glue-0.2.3/src/lib.rs:102: error: undefined reference to 'cargo_apk_injected_glue_set_multitouch'
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

The fix:

cargo install cargo-apk

Install Gradle

The error:
> cargo apk build --release
error: Could not execute `gradle`. Did you
                install it? (If already installed on windows with `gradle.bat`
                in your path, you must customise the gradle command to
                `gradle.bat` with the CARGO_APK_GRADLE_COMMAND environment
                variable).
The fix:

Via Homebrew:

brew install gradle

jni.h

The error:
> cargo apk build
Compiling android_native_app_glue.c
/Users/ignlg/Library/Android/sdk/ndk/18.1.5063045/sources/android/native_app_glue/android_native_app_glue.c:18:10: fatal error: 'jni.h' file
      not found
#include <jni.h>
         ^~~~~~~
1 error generated.
error: process didn't exit successfully: `/Users/ignlg/Library/Android/sdk/ndk/18.1.5063045/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc /Users/ignlg/Library/Android/sdk/ndk/18.1.5063045/sources/android/native_app_glue/android_native_app_glue.c -c -o /Users/ignlg/Development/rust/android-test/target/android-artifacts/arm-linux-androideabi/android_native_app_glue.o --sysroot /Users/ignlg/Library/Android/sdk/ndk/18.1.5063045/platforms/android-18/arch-arm` (exit code: 1)
The fix: ???
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment