Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android NDK linking

I am trying to build an android application that calls into a C++ backend. This backend uses ZeroMQ for messaging. Per the android build page on the ZeroMQ guide, I have built a native toolchain of ndk version 6 and used that to (successfully) build ZeroMQ.

However, when I build my own .so with the JNI implementations, I can't seem to make everything load properly. Specifically, if I call System.LoadLibrary("zmq"), this completes successfully, but if I then call *System.LoadLibrary("my_lib")* I always get an UnsatisfiedLinkError complaining that:

Cannot load library reloc_library[1244]:   29 cannot locate zmq_msg_init'...

The libmy_lib.so has been generated several different ways, each with no success. After generating it, I always copies libmy_lib.so (as well as libzmq.so) to my android project's folder: libs/armeabi/.

# Compile all object files - this part was done for all options
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -fpic -c Client_Events.cpp \
Client Wrapper.cpp jni.cpp -I /opt/android-root/include/ -I /my/project/specific/stuff

# Option 1 - Don't link the lib in at all
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o 

# Option 2 - Link ZeroMQ in statically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
libzmq.a libstdc++.a -Wl,--whole-archive    

# Option 3 - Explicitly link ZeroMQ in dynamically
/opt/android-toolchain/bin/arm-linux-androideabi-g++ -shared  \
-Wl,-soname,libmy_lib.so -o libmy_lib.so jni.o Client_Events.o Client_Wrapper.o \
-L /opt/android-root/lib/ -lzmq

With each of these options I tried both explicitly calling System.LoadLibrary("zmq") before loading my own library and not. Nothing varied the results. Using nm confirms that, at least in the case of option #2, the missing symbol *zmq_msg_init* is indeed present in libmy_lib.so.

Any ideas as to why it cannot find the ZeroMQ symbols that are linked in?

like image 406
user1243488 Avatar asked Dec 10 '22 00:12

user1243488


1 Answers

I just learnt how to compile a 2nd library and link it to my main library in android ndk. Let me see if I am of any use to you.

The following is how I create my 2nd library (In my case, I build bullet physics library and the irrlicht rendering engine as 2 separate libraries for my game).

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := HEADER FILES 
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := SRC FILES

LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -ldl -llog

include $(BUILD_SHARED_LIBRARY)

Then copy your libxxxx.so (In my case, libbullet.so and libirrlicht.so) to your jni folder. And in your main library .mk file add the following.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for bullet)
LOCAL_MODULE := bullet
LOCAL_SRC_FILES := libbullet.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_C_INCLUDES := (includes for irrlicht)
LOCAL_MODULE := irrlicht
LOCAL_SRC_FILES := libirrlicht.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := (includes for bullet + includes for irrlicht + includes for main code)
LOCAL_SRC_FILES := main code src files

LOCAL_MODULE := gamescript

LOCAL_ARM_MODE   := arm
LOCAL_CFLAGS := $(LOCAL_C_INCLUDES:%=-I%) -O3 -DANDROID_NDK -DDISABLE_IMPORTGL
LOCAL_LDLIBS := -lOpenSLES -landroid -ldl -llog

LOCAL_SHARED_LIBRARIES := bullet irrlicht

include $(BUILD_SHARED_LIBRARY)

And now, add all the libraries to your java code in right order.

System.loadLibrary("bullet");
System.loadLibrary("irrlicht");
System.loadLibrary("gamescript");
like image 189
codetiger Avatar answered Jan 03 '23 13:01

codetiger