badicsalex / ar-drivers-rs

Opensource Rust driver for various AR glasses
MIT License
132 stars 21 forks source link

Unable to cross compile for Android #5

Closed sn99 closed 1 year ago

sn99 commented 1 year ago

Running cargo build --target aarch64-linux-android --verbose gives

cargo  build --target aarch64-linux-android --verbose
       Fresh autocfg v1.1.0
       Fresh cc v1.0.79
       Fresh pkg-config v0.3.27
       Fresh bytemuck v1.13.1
       Fresh num-traits v0.2.16
       Fresh safe_arch v0.7.1
       Fresh rawpointer v0.2.1
       Fresh cfg-if v1.0.0
       Fresh static_assertions v1.1.0
       Fresh bitflags v1.3.2
       Fresh scopeguard v1.2.0
       Fresh libc v0.2.147
       Fresh approx v0.5.1
       Fresh num-integer v0.1.45
       Fresh num-complex v0.4.3
       Fresh wide v0.7.11
       Fresh paste v1.0.14
   Compiling hidapi v2.4.1
       Fresh matrixmultiply v0.3.7
       Fresh bitflags v2.0.2
       Fresh tinyjson v2.5.1
       Fresh byteorder v1.4.3
     Running `/home/sn99/Downloads/ar-drivers-rs-master/target/debug/build/hidapi-244def70a3e3da47/build-script-build`
       Fresh nix v0.26.2
   Compiling simba v0.8.1
       Fresh typenum v1.16.0
       Fresh num-rational v0.4.1
   Compiling libusb1-sys v0.6.4
   Compiling rusb v0.9.2
     Running `/home/sn99/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name simba --edition=2018 /home/sn99/.cargo/registry/src/index.crates.io-6f17d22bba15001f/simba-0.8.1/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=80 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="std"' --cfg 'feature="wide"' -C metadata=47ec6e6ace1412ee -C extra-filename=-47ec6e6ace1412ee --out-dir /home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps --target aarch64-linux-android -C linker=/home/sn99/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/debug/deps --extern approx=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libapprox-ef5258c943a15217.rmeta --extern num_complex=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libnum_complex-2675a163087bd6a6.rmeta --extern num_traits=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libnum_traits-6407d669dc13bf7f.rmeta --extern paste=/home/sn99/Downloads/ar-drivers-rs-master/target/debug/deps/libpaste-b8a4ca751342c3a9.so --extern wide=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libwide-1c39544f96c044a6.rmeta --cap-lints allow`
   Compiling serialport v4.2.2
     Running `/home/sn99/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name libusb1_sys --edition=2018 /home/sn99/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libusb1-sys-0.6.4/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=80 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=201450028b344926 -C extra-filename=-201450028b344926 --out-dir /home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps --target aarch64-linux-android -C linker=/home/sn99/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/debug/deps --extern libc=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/liblibc-ee138b075719b2ac.rmeta --cap-lints allow -L native=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/build/libusb1-sys-45fa8d6d74cfaa9d/out -l static=usb-vendored`
     Running `/home/sn99/Downloads/ar-drivers-rs-master/target/debug/build/rusb-081683cded2a227a/build-script-build`
     Running `/home/sn99/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustc --crate-name serialport --edition=2018 /home/sn99/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serialport-4.2.2/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=80 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="default"' --cfg 'feature="libudev"' -C metadata=61d56f0899571aa3 -C extra-filename=-61d56f0899571aa3 --out-dir /home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps --target aarch64-linux-android -C linker=/home/sn99/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps -L dependency=/home/sn99/Downloads/ar-drivers-rs-master/target/debug/deps --extern bitflags=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libbitflags-24e29694f72f86d5.rmeta --extern cfg_if=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libcfg_if-931c0cdcdfd6cc3b.rmeta --extern nix=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libnix-90801f53a5fdd38b.rmeta --extern scopeguard=/home/sn99/Downloads/ar-drivers-rs-master/target/aarch64-linux-android/debug/deps/libscopeguard-8d68803e22ce5110.rmeta --cap-lints allow`
error: failed to run custom build command for `hidapi v2.4.1`

Caused by:
  process didn't exit successfully: `/home/sn99/Downloads/ar-drivers-rs-master/target/debug/build/hidapi-244def70a3e3da47/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-changed=etc/hidapi/linux/hid.c
  cargo:rerun-if-env-changed=LIBUSB_1.0_NO_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
  cargo:rerun-if-env-changed=PKG_CONFIG_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_aarch64-linux-android
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_aarch64_linux_android
  cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
  cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR

  --- stderr
  thread 'main' panicked at 'Unable to find libusb-1.0: "pkg-config has not been configured to support cross-compilation.\n\nInstall a sysroot for the target platform and configure it via\nPKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a\ncross-compiling wrapper for pkg-config and set it via\nPKG_CONFIG environment variable."', /home/sn99/.cargo/registry/src/index.crates.io-6f17d22bba15001f/hidapi-2.4.1/build.rs:72:60
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish...

I went through this https://github.com/ruabmbua/hidapi-rs/issues/122 issue too, to find any hints but alas.

My env looks something like this:

export ANDROID_HOME=$HOME/Android/Sdk
export ANDROID_NDK_HOME=/home/sn99/Android/Sdk/ndk/25.2.9519653

export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export TARGET=aarch64-linux-android
export API=33

export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export AS=$CC
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip

export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$TOOLCHAIN/bin

And .cargo/config looks like this:

[target.aarch64-linux-android]
linker = "/home/sn99/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang"
badicsalex commented 1 year ago

Heh, I was never actually solved this properly.

First off, you need to cross-compile a libusb.so (it's just cd libusb/android; $ANDROID_NDK_HOME/ndk-build libs/armeabi-v7a/libusb1.0.so APP_ABI=armeabi-v7a APP_PLATFORM=android-$API)

Then I use a file called fake-pk-config.sh with these contents:

if [[ "$1" == "--libs" && "$2" == "--cflags" ]]; then
    case "$3" in
        "libusb-1.0")
            echo "-I$BASE_DIR/libusb/libusb -L$BASE_DIR/libusb/android/libs/armeabi-v7a -lusb1.0"
            ;;

        *)
            echo "Unsupported lib" >&2
            exit 1
            ;;
    esac
elif [[ "$1" == "--modversion" ]]; then
    case "$2" in
        "libusb-1.0")
            echo "1.0.26"
            ;;

        *)
            echo "Unsupported lib" >&2
            exit 1
            ;;
    esac
else
    echo "Unsupported args." >&2
    exit 1
fi

And export PKG_CONFIG="$BASE_DIR/fake-pkg-config.sh". You could probably make the actual pkg-config work properly (with the PKG_CONFIG* env vars and creating a libusb.pc file), but I never really cared :P

An alternative would be properly implementing https://github.com/badicsalex/tiny-linux-usb and then using that instead of both rusb and hidapi. I did try it with the nreal air driver, and it can be made to work on Android, but it'd take at least a week of real work.

badicsalex commented 1 year ago

OK, just writing this down made me so ashamed that I got rid of fake-pkg-config.sh. Now my build-android.sh looks like this (libusb is added to the git repo as a submodule):


set -e

SCRIPT="$(readlink -f "$0")"
export BASE_DIR="$(dirname "$SCRIPT")"

export ANDROID_NDK="/opt/android_sdk/ndk/25.2.9519653/"
export TOOLCHAIN="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64"
export TARGET="armv7a-linux-androideabi"
export API="29"
export ANDROID_PLATFORM=android-$API
export ANDROID_NATIVE_API_LEVEL=$API
export ANDROID_ARM_NEON=TRUE
export AR="$TOOLCHAIN/bin/llvm-ar"
export CC="$TOOLCHAIN/bin/$TARGET$API-clang"
export AS="$CC"
export CXX="$TOOLCHAIN/bin/$TARGET$API-clang++"
export LD="$TOOLCHAIN/bin/ld"
export RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
export STRIP="$TOOLCHAIN/bin/llvm-strip"
export PKG_CONFIG_PATH="$BASE_DIR/libusb_install/lib/pkgconfig"
export PKG_CONFIG_ALLOW_CROSS=1
export CFLAGS="-march=armv7-a -mfpu=neon"

if [[ ! -f "$BASE_DIR/libusb_install/lib/libusb-1.0.so" ]]; then (
    echo
    echo " == BUILDING LIBUSB == "
    echo
    cd libusb
    ./bootstrap.sh
    ./configure \
        --host armv7a-linux-androideabi \
        --prefix=$BASE_DIR/libusb_install \
        --enable-udev=false \
        --enable-system-log
    make -j
    make install
) fi

cargo build --target armv7-linux-androideabi --release --lib
badicsalex commented 1 year ago

You could probably set the prefix of your libusb ./configure call to the sysroot of your ndk, install it there, and use PKG_CONFIG_SYSROOT_DIR instead. But I'm uncomfortable putting additional files into that sysroot.

sn99 commented 1 year ago

Thanks for you help @badicsalex I was able to reproduce your steps, here is my build-android.sh:

#!/bin/bash

set -e

SCRIPT="$(readlink -f "$0")"
export BASE_DIR="$(dirname "$SCRIPT")"

# export ANDROID_NDK="/home/sn99/Android/Sdk/ndk/25.2.9519653/"
export TOOLCHAIN="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64"
export TARGET="aarch64-linux-android"
export API="33"
export ANDROID_PLATFORM=android-$API
export ANDROID_NATIVE_API_LEVEL=$API
export AR="$TOOLCHAIN/bin/llvm-ar"
export CC="$TOOLCHAIN/bin/$TARGET$API-clang"
export AS="$CC"
export CXX="$TOOLCHAIN/bin/$TARGET$API-clang++"
export LD="$TOOLCHAIN/bin/ld"
export RANLIB="$TOOLCHAIN/bin/llvm-ranlib"
export STRIP="$TOOLCHAIN/bin/llvm-strip"
export PKG_CONFIG_PATH="$BASE_DIR/libusb_install/lib/pkgconfig"
export PKG_CONFIG_ALLOW_CROSS=1
export CFLAGS="-march=armv8-a"

if [[ ! -f "$BASE_DIR/libusb_install/lib/libusb-1.0.so" ]]; then
    (
    echo
    echo " == BUILDING LIBUSB == "
    echo
    cd libusb
    ./bootstrap.sh
    ./configure \
        --host $TARGET \
        --prefix=$BASE_DIR/libusb_install \
        --enable-udev=false \
        --enable-system-log
    make -j
    make install
    )
fi

cargo build --target $TARGET --release --lib

And .cargo/config looks like this:

[target.aarch64-linux-android]
linker = "/home/sn99/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android33-clang++"
sn99 commented 1 year ago

@badicsalex Sorry for disturbing you again but now I am getting a runtime error (it builds though):

08-25 16:30:06.569 27157 27157 E AndroidRuntime: FATAL EXCEPTION: main
08-25 16:30:06.569 27157 27157 E AndroidRuntime: Process: tech.subcom.shepherd, PID: 27157
08-25 16:30:06.569 27157 27157 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: library "libusb-1.0.so" not found: needed by /data/app/~~NGFfCGYaHQB3DLarljH9Cw==/tech.subcom.shepherd-aUWkQ82xuUhS6yuCPl5-fg==/base.apk!/lib/arm64-v8a/libshepherd_android_rust.so in namespace classloader-namespace
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at java.lang.System.loadLibrary(System.java:1664)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at tech.subcom.shepherd.ShepherdService.<clinit>(ShepherdService.java:16)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at java.lang.Class.newInstance(Native Method)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.app.AppComponentFactory.instantiateService(AppComponentFactory.java:129)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at androidx.core.app.CoreComponentFactory.instantiateService(CoreComponentFactory.java:75)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.app.ActivityThread.handleCreateService(ActivityThread.java:4523)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.app.ActivityThread.access$100(ActivityThread.java:287)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2189)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:106)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:255)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:8212)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
08-25 16:30:06.569 27157 27157 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
badicsalex commented 1 year ago

You have to put the built libusb-1.0.so file into your jniLibs directory, right next to the rust .so.

sn99 commented 1 year ago

Ahhh, thanks again, I got it working by placing libusb_install/lib/ -> app/src/main/jniLibs/arm64-v8a.