2

I'm writing an Android application that relies on two prebuilt shared libraries (A and B). Both libraries are configured to work with the armeabi and armeabi-v7a architectures.

The first prebuilt library, A, is libsodium. The second prebuilt library, B, is a Rust library that depends on libsodium. When compiling the Rust prebuilt library, libsodium is used as a dependency.

Right now, I want to use my two prebuilt libraries, A & B, in my Android application. Loading A using System.loadLibrary() works just fine. But when I load B, there's an error that B can't find a method defined in A:

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "crypto_sign_ed25519_detached" referenced by "libB.so"...

My Android.mk is as follows:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := sodium
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/libsodium.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/sodium.h $(LOCAL_PATH)/include/sodium/
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := rust
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/librust.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/sodium.h $(LOCAL_PATH)/include/sodium/
LOCAL_SHARED_LIBRARIES := sodium
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := rust-manager
LOCAL_SRC_FILES := rust-manager.c
LOCAL_SHARED_LIBRARIES := rust sodium
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ $(LOCAL_PATH)/include/sodium.h $(LOCAL_PATH)/include/sodium/
include $(BUILD_SHARED_LIBRARY)

The rust-manager.c file is my C wrapper generated using javah that contains C functions that map my native Java functions to the Rust library, but I think it's negligible at this point. Any help would be much appreciated!

Raed M
  • 63
  • 7
  • I take it that you've already loaded library A when loading library B? Can you try `arm-linux-androideabi-nm -D libA.so | grep crypto_sign_ed25519_detached` and similarly for libB.so? (You find the `nm` binary in `NDK/toolchains/arm-linux-androideabi-4.*/prebuilt/*/bin`.) – mstorsjo Nov 25 '15 at 18:11
  • That's right, A is being loaded before B. Just ran nm and received the following outputs: `T crypto_sign_ed25519_detached for libA.so U crypto_sign_ed25519_detached for libB.so` Any idea what this means? – Raed M Nov 25 '15 at 18:32
  • I assume the former had a nonzero hex address printed before the `T`, while the latter had empty space before the `U`? This just means that libA.so has a definition for the symbol, and libB.so has an undefined symbol with that name. So given that, it does seem correct. – mstorsjo Nov 25 '15 at 19:03
  • Oh interesting. Could this mean that libB has been configured incorrectly or that some undesirable optimization could have occurred that omitted this method from the final object? – Raed M Nov 25 '15 at 19:12
  • No, it means that libB uses this function (or variable), and libA provides it - which all seems just correct, just as it should be. The questions is why it isn't found when you already have loaded libA, when trying to load libB. – mstorsjo Nov 25 '15 at 19:20

1 Answers1

1

After a days worth of work, the problem was with the version of libsodium that I was using (1.0.6). I found that the undefined symbols when running ndk-build vary based on the version used. Using libsodium v1.0.3 solved my problems!

Raed M
  • 63
  • 7