Target older android NDK with armv7-linux-androideabi

Hey, I'm playing around with building android apps for old Blackberry devices running BB10. Unfortunately to build anything to run on these devices you need to target android API level 18 and if you want native code target an older NDK that still supports API level 18.

I'm not really familiar with the rust runtime and its dependencies, but to try and get something built I built a static library in rust with armv7-linux-androideabi as the target. I then setup a simple Android.mk file to build an Android compatible .so library. Unfortunately I got the following errors when trying to link against the static library, which I think come from the rust runtime building against a newer version of the ndk.

lfryzek@hazepad:~/Documents/projects/bb10/libmatrix/clib$ ~/Android/Sdk/ndk/android-ndk-r14b/ndk-build APP_PLATFORM=android-18 APP_ABI=armeabi-v7a NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk
Android NDK: WARNING:Android.mk:matrix: non-system libraries in linker flags: ../target/armv7-linux-androideabi/debug/liblibmatrix.a    
Android NDK:     This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES    
Android NDK:     or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the    
Android NDK:     current module    
[armeabi-v7a] SharedLibrary  : liblibmatrix.so
library/std/src/../../backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs:27: error: undefined reference to 'dl_iterate_phdr'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [obj/local/armeabi-v7a/liblibmatrix.so] Error 1

Without rebuilding the whole toolchain can I rebuild the runtime? If not are there instructions for building the androideabi runtimes to point them at a different ndk & api version?

The Android targets available in the rust compiler does not support those API levels. And it's not something you just add either.

Well, Windows 95 is also not supported by Rust, either, but adventurous people made it work. Perhaps talking to them and asking about how that was done may help.

It's not impossible, but you have to undo things such as this:

Thanks for the response. I was able to get it working. Instead of undoing those hacks I made a little shim c library that would re-export the missing symbols that are defined in the c headers as static inline. Additionally I had to rebuild the standard library with the panic mode set to "immediate_abort" to avoid the unwind code calling dl_iterate_phdr which isn't available on the old ndk for armv7a. A more detailed breakdown of what I did:

  1. You need to build stdlib for rust using an older version of the ndk. You can do this by creating a .cargo/config.toml file in your project that looks like this
[target.armv7-linux-androideabi]
ar = "<path to android-ndk-r23c>/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar"
linker = "<path to android-ndk-r23c>/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi18-clang"

Then you when you build your project using cargo ndk, make sure you add the arg -Z build-std to tell it to build the standard library from source. Note you also have to have ANDROID_NDK_ROOT env var set to the android-ndk-r23c path on your system.
2. To avoid the issue with dl_iterate_phdr you can change the panic mode to immediate abort in your Cargo.toml file.

[profile.release]
panic = "immediate-abort"

[profile.dev]
panic = "immediate-abort"
  1. If you use rust code that calls some missing symbols like mkfifo, or signal you can make a little c stub to export the static inline function and then link that against your rust program. To re-export it you can do something like
#define signal real_signal
#include <signal.h>
#undef signal

__sighandler_t signal(int s, __sighandler_t f)
{
    return real_signal(s, f);
}