[NDK] dlopen failed: cannot locate symbol "rand" referenced by...
Development/Failure Log 2014. 11. 17. 10:59Problem:
11-13 15:08:17.982: E/dalvikvm(6149): dlopen("/data/app-lib/com.kugistory-1/libkugistory.so") failed: dlopen failed: cannot locate symbol "rand" referenced by "libkugistory.so"...
11-13 15:08:17.982: W/dalvikvm(6149): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/kugistory/NativeImageProcessor;
11-13 15:08:17.982: D/AndroidRuntime(6149): Shutting down VM
11-13 15:08:17.982: W/dalvikvm(6149): threadid=1: thread exiting with uncaught exception (group=0x41b10ba8)
11-13 15:08:17.992: E/AndroidRuntime(6149): FATAL EXCEPTION: main
11-13 15:08:17.992: E/AndroidRuntime(6149): Process: com.kugistory, PID: 6149
11-13 15:08:17.992: E/AndroidRuntime(6149): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "rand" referenced by "libkugistory.so"...
11-13 15:08:17.992: E/AndroidRuntime(6149): at java.lang.Runtime.loadLibrary(Runtime.java:364)
11-13 15:08:17.992: E/AndroidRuntime(6149): at java.lang.System.loadLibrary(System.java:526)
11-13 15:08:17.992: E/AndroidRuntime(6149): at com.kugistory.NativeImageProcessor.<clinit>(NativeImageProcessor.java:8)
안드로이드 네이티브(native) 라이브러리를 사용하려다가 위와같은 에러가 생겼다.
찾아보니 ndk-r10의 버그인 듯 하다.
다음과 같은 어떤 사람의 말로는 32-bit, 64-bit 빌드 타입과 관련된 문제인 듯 하다.
You need to use the 32-bit NDK (android-ndk32-r10b-darwin-x86_64) if building for 32-bit targets.
In the ARM headers in the 32-bit target NDK, rand() is declared as a static inline function (and as such does not need to exist as a symbol in libc.so on ARM devices). In the ARM headers in the 64-bit target NDK, rand() is declared as a regular function, but since it does not exist in the libc.so on ARM devices, there is a runtime error. Ergo, use the 32-bit target NDK when targeting 32-bit platforms. Or tell Google that their shit is broken.
Trials:
이것을 stl static 라이브러리에서 shared 라이브러리 이용으로 바꾸면 된다는 말을 지나가다가 보고는 다음과 같이 시도했으나 실패했다.
Solution:
해결 방법을 찾는것은 매우 힘들었지만, 해결 방법 자체는 간단했다.
다음과 같이 Application.mk에서 대상 OS들을 몇가지 더 추가하자 거짓말처럼 문제가 풀렸다.
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a x86 mips # arm64-v8a x86_64 mips64
APP_PLATFORM := android-16
APP_OPTIM := release
NDK_TOOLCHAIN_VERSION := 4.8
참고로 Android.mk는 다음과 같이 설정해둔 상태였다.
OpenCV를 위한 설정 등 없어도 되는 줄들도 포함되어 있다.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_INSTALL_MODULES:= on
OPENCV_CAMERA_MODULES:= off
OPENCV_LIB_TYPE:= STATIC
include E:\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk
LOCAL_MODULE := Kugistory
FILE_LIST := $(wildcard $(LOCAL_PATH)/*.cpp)
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a-hard/include
LOCAL_LDLIBS += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/libgnustl_static.a
LOCAL_LDLIBS += -llog -ldl -lz
include $(BUILD_SHARED_LIBRARY)