Help to run the .so files in rust along with android

Hi team,
I want convert my Android JNI (C++ code) to support the Rust Programming language in Android.
Almost completed the Integrating Rust programming in android with help of the below url https://blog.csdn.net/u011376563/article/details/123200461.
I'm doing some R&D to integrate .so files into rust module using libloading but I'm failing if I run by using the command " cargo build --target aarch64-linux-android " getting below error

linker I:/GitHub_xxxx/ndk_standalone_25.1.8937393/arm64/bin/aarch64-linux-android-gcc not found

please help to resolve

It sounds like you don't have the Android NDK set up correctly, or maybe the Rust compiler needs to be told where the linker is.

Does that article have a section on configuring .cargo/config.toml or walk you through installing the NDK?

In the past, I've used the cargo ndk helper to make sure my toolchain is set up correctly and do the compiling.

this is my .cargo/config.toml

[target.aarch64-linux-android]
ar = "I:/GitHub_xxxx/ndk_standalone_25.1.8937393/arm64/bin/aarch64-linux-android-ar"
linker = "I:/GitHub_xxx/ndk_standalone_25.1.8937393/arm64/bin/aarch64-linux-android-gcc"
[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

Does I:/GitHub_xxx/ndk_standalone_25.1.8937393/arm64/bin/aarch64-linux-android-gcc exist in the first place?

GCC has been removed since NDK r18b. You must use the llvm toolchain instead.

can you please elaborate how to use llvm ?

You do not need to make standalone toolchain anymore, use the prebuilt llvm toolchain that is located at this path: ${NDK_PATH}/toolchains/llvm/prebuilt/${HOST_TAG}.

Where ${HOST_TAG} is windows_x86-64 if you are developing on a Windows machine.

So for the linker targeting [target.aarch64-linux-android], you would use clang instead of gcc: ${NDK_PATH}/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang

The android SDK level has to be specified (here android21) and defines the lowest Android version that you want to support (newer versions will be compatible).

Thank you so much for giving such a nice explanation.
few more doubts I had

  1. If I run this command "cargo ndk -t armeabi-v7a -t arm64-v8a -o ./jniLibs build --release" .so file able to generate in corresponding targets. but If I run this command "cargo build --target aarch64-linux-android " getting error like

linker I:\GitHub_xxxxx\${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android33-clang not found

may I know the difference and whats happening ?

  1. what is the approach to use/load .so files in rust project ?

The path I:\GitHub_xxxxx\${ANDROID_NDK_HOME} is probably not correct. ANDROID_NDK_HOME env variable should contains an absolute path to the NDK directory, so it should not be used relatively to another path.

So, this would be ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android33-clang.

I didn't know you used cargo-ndk. You should not define the linker and ar in .cargo/config.toml in this case, this is handled by the tool. You just have to make sure the environment variable ANDROID_NDK_HOME points to your NDK installation.

I may not understand your use case correctly. But linking to .so files in rust is the same whether you are exporting a cdylib with JNI support or a normal rlib. If you happen to depends on OpenSSL for example, just link to it normally using the appropriate "sys" crate (openssl-sys in this case). But this is generally treated by the high-level crate you depends on.

I changed my .cargo/config.toml as below
[target.aarch64-linux-android]
linker = "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android33-clang"

[target.armv7-linux-androideabi]
linker = "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/armv7a-linux-androideabi33-clang"

[target.i686-linux-android]
linker = "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android33-clang"

[target.x86_64-linux-android]
linker = "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android33-clang"
[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

here ANDROID_NDK_HOME pointed to NDK original path in environment variables.
I:\GitHub_xxxxx\ ==> this path is project workspace
system itself returning the whole path.

I want use third party shared object library files in rust project(like how we will use system.loadlibrary(".so file") in java), I don't have idea to implement this.

The problem is probably that ${ANDROID_NDK_HOME} is not expanded and the path resolve to I:\GitHub_xxxxx\${ANDROID_NDK_HOME}/... which does not exist.

I do not work using Windows so I do not know what would be the syntax in Windows for expressing environment variables in this file. For simplicity, as this is not a configuration file that is meant to be shared automatically and stored in the project folder, I'd just copy the full path of ANDROID_NDK_HOME in this file.

means I have to define like this

Yes, that would be the way to go. Sorry about the misdirections but I don't have experience working on Windows so I don't specifically know how these are handled on this OS. You should always convert paths from instructions to your environment as path formatting is generally specific to the OS.

Note that this should work because the ${ANDROID_HOME}/ndk-bundle is frozen to release 22 which is still compatible with how Rust links to libgcc. From release 23, NDK drop libgcc and you would need custom operations to tell rust how to link against this NDK. I would suggest to use cargo-ndk as already suggested (then delete .cargo/config.toml as it can only bring inconsistencies here). This tool makes what is necesseray to link against latest NDK releases.

Ok, Thank you :+1:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.