Closed sn99 closed 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.
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
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.
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++"
@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)
You have to put the built libusb-1.0.so file into your jniLibs directory, right next to the rust .so.
Ahhh, thanks again, I got it working by placing libusb_install/lib/
-> app/src/main/jniLibs/arm64-v8a
.
Running
cargo build --target aarch64-linux-android --verbose
givesI 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:
And
.cargo/config
looks like this: