Android ndk undefined reference using crypto++ - android

So i have build a static Libary of Crypto++ for Android.
I want to build my own libary now and use the crypto++ libary.
For the Build I use this Android mk:
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := StaticLibrary3.cpp
LOCAL_STATIC_LIBRARIES := crypt
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := crypt
LOCAL_SRC_FILES := libcryptopp.a
include $(PREBUILT_STATIC_LIBRARY)
Now when i link the libary into the project, i get a lot of errors about undefined referneces like this:
string.c:600: error: undefined reference to 'std::__stl_throw_length_error(char const*)
or
alloc.h:158: error: undefined reference to 'std::__node_alloc::_M_allocate(unsigned int&)
What have i done wrong?

Your Application.mk must define APP_STL that fits the STL settings used for the prebuilt cryptopp library.

Related

Non-system libraries in linker flags: -lopencv_java3

In the android.mk file I want to include the OpenCV3 library. so the file looks like this:
android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := D:\path to\OpenCV-android-sdk\sdk\native\jni\include
include D:\path to\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
LOCAL_MODULE := MyLib
LOCAL_SRC_FILES := file1.cpp
LOCAL_SRC_FILES += file2.cpp
OPENGLES_LIB := -lGLESv1_CM
OPENGLES_DEF := -DUSE_OPENGL_ES_1_1
LOCAL_LDLIBS += -lGLESv1_CM -ldl -llog
include $(BUILD_SHARED_LIBRARY)
But when I build the project, I got this warning message:
Android NDK: WARNING:jni/Android.mk:MyLib: non-system libraries in linker flags: -lopencv_java3
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
How can I solve this issue ?
If you only use OpenCV from your C++ code, you don't need this libopencv_java.so. To indicate this, add
OPENCV_LIB_TYPE=STATIC
Before including OpenCV.mk.
Some explanations can be found at answers.opencv.org.
Try using LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the current module
Depending on which version you have (static/dylibs), change your LOCAL_LDLIBS to either LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES
Android.mk is a good reference to variables in the Android makefile

ANDROID: How to properly link against static libraries while creating shared libraries with dependencies on the static ones

I have to use some c++ code in my android application. This code was used successfully in an iOS project.
The code depends on 2 external libraries: zero-mq and protocol buffers.
I compiled the zmq library as an static library like explained here. I added the static (.a) library and the .jar to my project.
I created the protobuf library with the following configurations:
./configure --host=arm-eabi --with-sysroot=x/android-ndk-r10d/platforms/android-21/arch-arm CC="x/android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --sysroot x/android-ndk-r10d/platforms/android-21/arch-arm" --enable-cross-compile --with-protoc=protoc LIBS=-lc
make
I changed the real directories to x to make them shorter.
In my Android Project(IDE: Android Studio) I prepared everything which is necessary. I created a JNI Folder and deactivated the auto-creation of the makefiles.
Application.mk:
APP_MODULE := proxy
APP_STL := gnustl_shared
APP_CPPFLAGS := -frtti -fexceptions --std=c++11
APP_ABI := armeabi-v7a ##all later
NDK_TOOLCHAIN_VERSION := 4.9
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := zmq_static
LOCAL_SRC_FILES := zmq/libzmq.a
include $(PREBUILD_STATIC_LIBRARY)
LOCAL_MODULE := protobuf_static1
LOCAL_SRC_FILES := protobuf/libprotobuf.a
LOCAL_EXPORT_C_INCLUDES := google/protobuf protobuf/
include $(PREBUILD_STATIC_LIBRARY)
LOCAL_MODULE := protobuf_static2
LOCAL_SRC_FILES := protobuf/libprotobuf-lite.a
LOCAL_EXPORT_C_INCLUDES := google/protobuf protobuf/
include $(PREBUILD_STATIC_LIBRARY)
LOCAL_MODULE := protobuf_static3
LOCAL_SRC_FILES := protobuf/libprotoc.a
LOCAL_EXPORT_C_INCLUDES := google/protobuf protobuf/
include $(PREBUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := proxy
LOCAL_CFLAGS := -I/include -pthread -lpthread -D__GXX_EXPERIMENTAL_CXX0X__ - frtti
LOCAL_CPPFLAGS := -I/include -pthread -lpthread -D__GXX_EXPERIMENTAL_CXX0X__ -frtti
LOCAL_CPP_FEATURES += exceptions
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := \
usersession.cpp\
## LOCAL_ALLOW_UNDEFINED_SYMBOLS := true will compile the code but shutdown on runtime
LOCAL_C_INCLUDES += C:\Users\M\Dropbox\Workspace\ndk_swig_test\app\src\main\jni
LOCAL_C_INCLUDES += C:\Users\M\Dropbox\Workspace\ndk_swig_test\app\src\arm\jni
LOCAL_C_INCLUDES += C:\Users\M\Dropbox\Workspace\ndk_swig_test\app\src\debug\jni
LOCAL_C_INCLUDES += C:\Users\M\Dropbox\Workspace\ndk_swig_test\app\src\armDebug\jni
LOCAL_C_INCLUDES += \zmq
LOCAL_C_INCLUDES += \protobuf
LOCAL_STATIC_LIBRARIES := zmq_static protobuf_static1 protobuf_static2 protobuf_static3
LOCAL_WHOLE_STATIC_LIBRARIES := zmq_static protobuf_static1 protobuf_static2 protobuf_static3
include $(BUILD_SHARED_LIBRARY)
The zmq library is in the subdirectory zmq and the protobuf library is in the subfolder protobuf.
Now the linking of the Objects still does not work. The Error Output when I execute ndk-build:
C:\Users\M\Dropbox\Workspace\ndk_swig_test\app\src\main\jni>ndk-build
[armeabi-v7a] SharedLibrary : libproxy.so
C:/Users/M/Documents/ndk/sources/cxx-stl/gnu- libstdc++/4.9/include/ext/new_allocator.h:127: error: undefined reference to 'ControlledInstance::ControlledInstan (std::shared_ptr<protogen::Application>, std:
:shared_ptr<protogen::Role>, std::shared_ptr<protogen::User>)'
C:/Users/M/Documents/ndk/sources/cxx-stl/gnu- libstdc++/4.9/include/bits/shared_ptr_base.h:511: error: undefined reference to 'protogen::User::User()'
C:/Users/M/Documents/ndk/sources/cxx-stl/gnu- libstdc++/4.9/include/bits/shared_ptr_base.h:914: error: undefined reference to 'google::protobuf::internal::empty tring_'
C:/Users/M/Dropbox/Workspace/ndk_swig_test/app/src/main//jni/controlledinstance.h :23: error: undefined reference to 'protogen::MetaGraph::~MetaGraph()'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [C:/Users/M/Dropbox/Workspace/ndk_swig_test/app/src/main//obj/local/armeabi- v7a/libproxy.so] Error 1
I tried many versions of the Android.mk and recreated the library more than once with different options which I found all over the internet.
I also looked at dozens of threads on stackoverflow which did not help me.(I'm not allowed to link them because of low reputation)
Additionally i read most of the doc files from the ndk e.g. PREBUILTS.
I added some other directories to my JNI directory e.g. the directory with the original files and directories (compiler, io, stubs...). I think this directory should offer the export of the necessary methods if the prebuild library was successfully linked to my shared library - which is not the case.
I tried far more than I can explain in few minutes and I think it would be overkill if i added everything I've tried because nothing helped.
Because this is my first question I dont have the reputation to include more than 2 links. Sorry for that.
There may probably be other issues as well, but you at least have got a typo - it should be include $(PREBUILT_STATIC_LIBRARY), as in, BUILT, not BUILD.

WARNING: .../Android.mk: non-system libraries in linker flags

I'm getting this warning while running $ANDROID_NDK_ROOT/ndk-build. The Android.mk is below.
$ $ANDROID_NDK_ROOT/ndk-build
WARNING:/Users/jwalton/Android-CryptoPP/jni/Android.mk:prng:
non-system libraries in linker flags: -lcryptopp -lstlport_shared
This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES
or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the
current module
...
However, when I follow the instructions and remove -lcryptopp -lstlport_shared from LOCAL_LDLIBS, then I get link errors related to symbols from libstlport_shared.so. A sample of the errors are shown below after the Android.mk file.
How, exactly, does ndk-build want Android.mk set up?
Why do I have to add $(STLPORT_INCL) to LOCAL_C_INCLUDES, and $(STLPORT_LIB) to LOCAL_LDFLAGS? Why does APP_STL := stlport_shared not setup the STL correctly out of the box?
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi
TARGET_ABI := android-9-armeabi
CRYPTOPP_INCL := /usr/local/cryptopp-android-9/include
CRYPTOPP_LIB := /usr/local/cryptopp-android-9/lib
STLPORT_INCL := /opt/android-ndk-r9/sources/cxx-stl/stlport/stlport
STLPORT_LIB := /opt/android-ndk-r9/sources/cxx-stl/stlport/libs/armeabi
APP_STL := stlport_shared
APP_MODULES := stlport_shared cryptopp
LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_C_INCLUDES := $(CRYPTOPP_INCL) $(CRYPTOPP_INCL)/cryptopp $(STLPORT_INCL)
LOCAL_LDFLAGS := -L $(CRYPTOPP_LIB) -L $(STLPORT_LIB)
LOCAL_LDLIBS := -lcryptopp -lstlport_shared -llog -landroid
# LOCAL_LDLIBS := -llog -landroid
# LOCAL_SHARED_LIBRARIES := -lcryptopp -lstlport_shared
LOCAL_MODULE := prng
LOCAL_SRC_FILES := libprng.cpp
include $(BUILD_SHARED_LIBRARY)
Here is a sample of the error when trying to follow the advice by removing my local libraries from LOCAL_LDLIBS:
$ $ANDROID_NDK_ROOT/ndk-build
Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 9 in /Users/jwalton/Android-CryptoPP/AndroidManifest.xml
Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
Gdbsetup : libs/armeabi/gdb.setup
Compile++ thumb : prng <= libprng.cpp
SharedLibrary : libprng.so
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: /Users/jwalton/Android-CryptoPP/obj/local/armeabi/objs-debug/prng/libprng.o: in function std::__node_alloc::allocate(unsigned int&):/opt/android-ndk-r9/sources/cxx-stl/stlport/stlport/stl/_alloc.h:158: error: undefined reference to 'std::__node_alloc::_M_allocate(unsigned int&)'
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: /Users/jwalton/Android-CryptoPP/obj/local/armeabi/objs-debug/prng/libprng.o: in function std::__node_alloc::deallocate(void*, unsigned int):/opt/android-ndk-r9/sources/cxx-stl/stlport/stlport/stl/_alloc.h:161: error: undefined reference to 'std::__node_alloc::_M_deallocate(void*, unsigned int)'
/opt/android-ndk-r9/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: /Users/jwalton/Android-CryptoPP/obj/local/armeabi/objs-debug/prng/libprng.o: in function std::ios_base::_M_check_exception_mask():/opt/android-ndk-r9/sources/cxx-stl/stlport/stlport/stl/_ios_base.h:193: error: undefined reference to 'std::ios_base::_M_throw_failure()'
...
I interpret the "non-system libraries in linker flags" message as a warning that you're not using the default system libraries (in usr/lib) which may be perfectly fine, but which could also lead to errors (incompatibility between different libraries versions). Whether this warning bugs you is completely up to you.
Then, about the way you tried to solve it, I think you're using wrongly the LOCAL_SHARED_LIBRARIES variable of the NDK.
I paste here a sample from one of my Android.mk file which uses Assimp
#------------------------------------------------------------------ Assimp
include $(CLEAR_VARS)
LOCAL_MODULE := Assimp
LOCAL_EXPORT_C_INCLUDES := $(GENERATED_INCLUDE_PATH)/assimp/include
LOCAL_SRC_FILES := $(GENERATED_PATH)/assimp/lib/libassimp.a
include $(PREBUILT_STATIC_LIBRARY)
...
LOCAL_STATIC_LIBRARIES := \
Assimp \
<Your other libs here>
As you can see, I declare a LOCAL_MODULE with a custom name, set up a few variables and then include the PREBUILT_STATIC_LIBRARY script which tells the NDK to use this lib.
Then in LOCAL_STATIC_LIBRARIES I list the libraries I use with their module name, not as if this was a linker flag like you're doing here.
In your case, I believe you should do the following, for example for the stl
include $(CLEAR_VARS)
LOCAL_MODULE := STLPortShared
LOCAL_EXPORT_C_INCLUDES := <path to stlport includes>
LOCAL_SRC_FILES := <path to stlport library>
include $(PREBUILT_SHARED_LIBRARY)
...
#Notice the name, identical to the one specified for LOCAL_MODULE
LOCAL_SHARED_LIBRARIES = STLPortShared
I think this should do it. Of course, repeat the process for each libs that causes trouble, and don't forget the include(CLEAR_VARS) between each lib specification.

Android.mk Unable to link with libcrypto

Case:
I am building an app which uses libcrypto and libssl. I am trying to use prebuilt libcrypto.so and libssl.so and compile my application.
But I keep getting undefined reference errors.
My App/Android.mk
LOCAL_PATH := $(call my-dir)
my_LOCAL_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
LOCAL_PATH := $(my_LOCAL_PATH)
common_SRC_FILES := \
src/foo.c
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(common_SRC_FILES)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../openssl/include
LOCAL_SHARED_LIBRARIES += mylibssl mylibcrypto
include $(BUILD_STATIC_LIBRARY)
My App/mylibssl/Android.mk
Building mylibssl [from a prebuilt libssl.so]
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylibssl
LOCAL_SRC_FILES := libssl.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../openssl/include
include $(BUILD_PREBUILT)
My App/mylibcrypto/Android.mk
Building mylibcrypto [from a prebuilt libcrypto.so]
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylibcrypto
LOCAL_SRC_FILES := libcrypto.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_SUFFIX := .so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../openssl/include
include $(BUILD_PREBUILT)
I keep getting
error: undefined reference to 'BIO_new_mem_buf'
error: undefined reference to 'PEM_read_bio_X509_AUX'
error: undefined reference to 'BIO_free'
...
I have spent several hours trying to figure out and am totally stuck. Please help!
I am building an app which uses libcrypto and libssl... But I keep getting undefined reference errors.
error: undefined reference to 'BIO_new_mem_buf'
error: undefined reference to 'PEM_read_bio_X509_AUX'
error: undefined reference to 'BIO_free'
These are linker errors, and mean you are not linking against the OpenSSL library. Its probably a path problem, assuming you have an Android version of the OpenSSL library available.
If you need an an Android version of the OpenSSL library, then you can build it yourself or find it on Github. To build it yourself, see FIPS Library and Android (just ignore the FIPS stuff). The steps required are (and note the leading dot "." when running the script):
cd openssl-1.0.1f/
wget http://wiki.openssl.org/images/7/70/Setenv-android.sh
chmod a+x *.sh
. ./setenv-android.sh
./config shared no-ssl2 no-hw no-engine --openssldir=/usr/local/ssl/android-18/ <other options>
make depend
make all
For option two, you can search Github with https://www.google.com/q=openssl+android+site:github.com.
Building mylibcrypto [from a prebuilt libcrypto.so]
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylibcrypto
LOCAL_SRC_FILES := libcrypto.so
This is not going to produce expected results, and will likely result in a crash if you get it to work. The problem is Android uses 0.9.8, and you are probably building against 1.0.1.
What happens is Zygote loads OpenSSL 0.9.8 at startup (its the parent of all Android Java programs). When your app is launched, Zygote is forked so OpenSSL is already mapped into the address space. That means the version of OpenSSL you are carrying around is not loaded. Later, you crash because 0.9.8 and 1.0.1 are not binary compatible (i.e., they are ABI incompatible).
You are correct in building a wrapper shared object (mylibcrypto.so). However, mylibcrypto.so will need to statically link against OpenSSL to avoid the above problem. That is, mylibcrypto.so will need to link against libcrypto.a and libssl.a.

using pre-built static libraries for Android NDK development

I am trying to build an android application that uses static libraries from some existing c++ code. However I cannot seem to get things building, here are the steps I have taken so far..
I have ndk-r5b and have built the standalone toolchain as per ndk/docs/STANDALINE-TOOLCHAIN.html. I have then used the standalone toolchain compiler (arm-linux-androideabi-g++) instead of g++ for the CXX flag in the Makefile that compiles the static libraries I need. This compiles without errors and there are 3 static libraries produced.
Here is a code snippet of some of the flags used to build the prebuilt libraries:
CXX = arm-linux-androideabi-g++
SYSTEM_LIBS = -lstdc++ -lm
INCLUDE_PATH += ${NDK_PATH}/platforms/android-8/arch-arm/usr/include/
Here is a sample line that is produced from the makefile when compiling:
arm-linux-androideabi-g++ -c -DTIME_SIM -I./include -I/home/greg/dev/Android/android-ndk-r5b/platforms/android-8/arch-arm/usr/include/ -fpic -ggdb3 -SimTime.C -o SimTime.o
Next I build the app using ndk-build using the following for Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := engine
LOCAL_SRC_FILES := ../libs/libEngine.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := shmem
LOCAL_SRC_FILES := ../libs/libShMem.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := util
LOCAL_SRC_FILES := ../libs/libUtil.a
include $(PREBUILT_STATIC_LIBRARY)
# build server as a shared library
include $(CLEAR_VARS)
LOCAL_MODULE := libServer
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include
LOCAL_SRC_FILES := \
Server.C \
Router.C \
RouterMsgs.C \
Federation.C \
cripName.C \
ver.C \
JNIWrapper.cpp
LOCAL_STATIC_LIBRARIES := engine shmem util
include $(BUILD_SHARED_LIBRARY)
The prebuilt libraries compile fine using the standalone toolchain compiler given in the android ndk. However there are many unresolved references to ostream when linking the shared library to the prebuilt libraries using ndk-build. For exampe:
/home/android/obj/local/armeabi/libShMem.a(SubscriptionItem.o): In function `SUBSCRIPTION_ITEM::Print(std::basic_ostream<char, std::char_traits<char> >&)':/home/src/comm/SubscriptionItem.C:97: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
I assume I am missing some important flags or not doing something correct when I am compiling using the standalone compiler but any help or insight on this issue would be greatly appreciated as I cant seem to find this answer on google or in any of the android ndk docs. Thanks!
Well, you can actually fix that with creating a Application.mk file inside the same folder as the Android.mk file is, containing:
APP_STL := stlport_static
for using the static stlport that is located inside the Android NDK.
I had the same issue and resolved it by adding a module for the standard C++ library. The library linked by the ndk-build system is from the wrong location (platforms/android-9/arch-arm/usr/lib in my case).
include $(CLEAR_VARS)
LOCAL_MODULE := rightstdc
LOCAL_SRC_FILES := <path to the correct libstdc++.a>
include $(PREBUILT_STATIC_LIBRARY)
Add the module tag to the list of static libraries:
LOCAL_STATIC_LIBRARIES := engine shmem util rightstdc
The build/core/build-binary.mk prepends -L$(SYSROOT)/usr/lib if any libraries are specified in LOCAL_LDLIBS but in my case that is the wrong path.
I don't know if there is a missing step that should copy the correct libstdc++ to that location but the approach above will work.

Categories

Resources