[C++ or Other Android Development Languages] djc6535:
I am writing an android app that wants to make JNI calls into a shared library built in using the NDK. The trick is this shared library calls functions provided by OTHER shared libraries. The other shared libraries are C libraries that have been compiled elsewhere.

Here's what I've tried:

**My Environment:**

I'm working in Eclipse. I've added native support and have a jni library. In that library I have my code and a \lib directory where I have copied my other .so files.

**Attempt #1 Android.mk: Just telling it where the libs are**

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := native_lib

LOCAL_SRC_FILES := native_lib.cpp

LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog

LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1

LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2

include $(BUILD_SHARED_LIBRARY)
​

This builds just fine, but when I try to run I get errors indicating that dlopen(libnative_lib) failed because it couldn't load libsupport_lib1.

Coming here I found this:

stackoverflow.com/questions/6041934/can-shared-library-call-another-shared-library

which said that I needed to call load library on all necessary libraries. Great!

**Attempt #2 Opening each library first**

static {

System.loadLibrary("support_lib1");

System.loadLibrary("support_lib2");

System.loadLibrary("native_lib");

}
​

Again, this builds just fine, however when I run I get a new error:

couldn't load libsupport_lib1. findLibrary returned null.

Now we're getting somewhere. It must not be loading the libraries over to the target.

**Attempt #3 Copying .so files into project/libs/armeabi**

Didn't work. When Eclipse builds it deleted the files I dropped in there.

**Attempt #4 Creating a new module for each library**

So then I found this:

stackoverflow.com/questions/5463518/android-ndk-link-using-a-pre-compiled-static-library

It's about static libraries, but maybe I am having a similar problem. The gist is that I need to declare a module for each library. So my new Android.mk looks like this:

LOCAL_PATH := $(call my-dir)

#get support_lib1

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib1

LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so

include $(BUILD_SHARED_LIBRARY)

#get support_lib2

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib2

LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so

include $(BUILD_SHARED_LIBRARY)

#build native lib

include $(CLEAR_VARS)

LOCAL_MODULE := native_lib

LOCAL_SRC_FILES := native_lib.cpp

LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog

LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib1

LOCAL_LDLIBS += -L$(LOCAL_PATH)/lib/support_lib2

include $(BUILD_SHARED_LIBRARY)
​

This builds! Even better, armeabi has the sos now! Even *BETTER* I get the following messages when I try to run it (telling me that support_lib1 and 2 were opened by LoadLibrary:

Trying to load lib /data/app-lib/com.example.tst/libsupport_lib1.so

added shared lib /data/app-lib/com.example.tst/libsupport_lib1.so

no JNI_OnLoad found in /data/app-lib/com.example.tst/libsupport_lib1.so, skipping init

but then...

dlopen failed: Could not locate symbol func_that_exists_in_libsupport_lib.so referenced by libnative_lib.so

**Edit: Attempt 5: Use PREBUILT_SHARED_LIBRARY**

So I found this:

stackoverflow.com/questions/9870435/how-can-i-link-prebuilt-shared-library-to-android-ndk-project

which seems to be exactly what I'm asking. Their answer seems to be 'don't use 'build_shared_library' but instead 'use PREBUILT_SHARED_LIBRARY

Okay, let's try.

LOCAL_PATH := $(call my-dir)

#get support_lib1

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib1

LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib1.so

include $(PREBUILT_SHARED_LIBRARY)

#get support_lib2

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib2

LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/support_lib2.so

include $(PREBUILT_SHARED_LIBRARY)

#build native lib

include $(CLEAR_VARS)

LOCAL_MODULE := native_lib

LOCAL_SRC_FILES := native_lib.cpp

LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog

LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2

include $(BUILD_SHARED_LIBRARY)
​

Build... fails! The build complains about missing symbols now.

**Edit: Attempt 6: Flatten everything**

So I went back to the prebuilts documentation in the NDK. It says:

Each prebuilt library must be declared as a single independent module to the build system. Here is a trivial example where we assume that the file "libfoo.so" is located in the same directory than the Android.mk below:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := foo-prebuilt

LOCAL_SRC_FILES := libfoo.so

include $(PREBUILT_SHARED_LIBRARY)
​

Notice that, to declare such a module, you really only need the following:

Give the module a name (here 'foo-prebuilt'). This does not need to correspond to the name of the prebuilt library itself.

Assign to LOCAL_SRC_FILES the path to the prebuilt library you are providing. As usual, the path is relative to your LOCAL_PATH.

Include PREBUILT_SHARED_LIBRARY, instead of BUILD_SHARED_LIBRARY, if you are providing a shared, library. For static ones, use PREBUILT_STATIC_LIBRARY.

A prebuilt module does not build anything. However, a copy of your prebuilt shared library will be copied into $PROJECT/obj/local, and another will be copied and stripped into $PROJECT/libs/<abi>.

So let's try flattening everything out to match the trivial example. I copied my libraries out of their cozy /lib folder and put them in the jni root. I then did this:

LOCAL_PATH := $(call my-dir)

#get support_lib1

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib1

LOCAL_SRC_FILES := support_lib1.so

include $(PREBUILT_SHARED_LIBRARY)

#get support_lib2

include $(CLEAR_VARS)

LOCAL_MODULE := support_lib2

LOCAL_SRC_FILES := support_lib2.so

include $(PREBUILT_SHARED_LIBRARY)

#build native lib

include $(CLEAR_VARS)

LOCAL_MODULE := native_lib

LOCAL_SRC_FILES := native_lib.cpp

LOCAL_LDLIBS := -L$(SYSROOT)/../usr/lib -llog

LOCAL_SHARED_LIBRARIES := support_lib1 support_lib2

include $(BUILD_SHARED_LIBRARY)
​

and... same error. Moreover I'm most definitely NOT seeing library files getting copied to $PROJECT/obj/local.

sooooo.... now what?