I am using a native library with my Android Studio project. I'm trying to utilize net-snmp, which is a C library (This is, unfortunately, a must-have. I cannot use alternatives as there is a larger native library which depends upon this.). We have compiled these into .so files and have done this correctly (To my knowledge, it compiles without errors in any case.).
However, whenever trying to load these library, I get the following error: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "endgrent" referenced by "libnetsnmp.so"...
This function is from grp.h which is included in every version of Android NDK. Here is the relavent section of the Android.mk file:
include $(CLEAR_VARS)
LOCAL_MODULE := NetSNMP
LOCAL_SRC_FILES := net-snmp/libnetsnmp.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/net-snmp/include
include $(PREBUILT_SHARED_LIBRARY)
I'm kind of new to NDK, but all the undefined symbol errors I found usually referred to it being unable to find the appropriate folder. As far as I know, this should be pulled in by Android NDK. Am I doing something wrong here? Is this just some error unrelated to the makefile?
UPDATE: Even after trying to move the grp.h file over to the includes I already have, I still find the same error.
So I'm pretty sure I figured this out, if someone else happens to have this problem. For some reason or another, this file simply just does not exist. Luckily, this was an alternative route (if it exists, call it instead). However, NDK does not understand if includes (but the compiler does, thus it was not put into the library).
So it searched for grp.h even though it had not been included. So, it crashed. Removing this, it fixed the error.
However, for anyone else venturing down this path, we began experiencing problems with the version numbers (it was crashing because it was trying to find 'foo.so.#'). If you make the version void within the makefile and recompile, this should also fix this issue. In future versions of NDK or Android, there may be a fix for version numbers, but there is not as of writing this. So getting rid of the version numbers is your best route right now.
Related
This is a 2 part question.
I'm currently in the process of converting our current build setup (Eclipse; ndk-build) to (hopefully) a better one (Android Studio; cmake).
I'm going down the cmake path because I read that that is the only way to get decent debugging to work properly without the need for the experimental gradle plugin (if you are sure this is false, please let me know).
Ok so first issue I'm having is simply linking static prebuilt libraries such as a prebuilt version of boost which I kind of have to use.
I've got some success from using the following strategy:
Add a library as a static prebuilt library that is searched for globally:
add_library(boost_thread STATIC IMPORTED GLOBAL)
Set the location of the prebuilt library:
set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION boost/lib/libboost_thread_pthread-gcc-mt-s-1_55.a)
Use stored value for prebuilt library when linking libraries:
target_link_libraries(myprog ${boost_thread} ...)
When I say I have had some success, I mean I saw some errors disappear but others remain (although it no longer complains it can't find the library to link). Am I missing a step?
The second problem is that I can't add the GLESv2 library which I see is also provided by the NDK. I also can't seem to find a single source stating how this should be done correctly. I've tried using find_package and find_library without success.
All I have in the Android.mk is LOCAL_LDLIBS := -lGLESv2 and so I tried to do set(CMAKE_CXX_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES} -lGLESv2) but that didn't work either (gives me /bin/sh: -lGLESv2: command not found).
First problem is supposed to be incredibly common and yet there seems to be little documentation explaining how it should be done. The second problem is maybe a little less common but probably still common enough that I'm surprised to find little to no help as to how to set it up.
I'm still having build issues but as far as the issues presented in the question are concerned, I think I have decent solutions:
To include a prebuilt static library:
add_library(boost_regex STATIC IMPORTED)
set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION /full/path/to/libboost_regex.a) # I'm using ${CMAKE_CURRENT_SOURCE_DIR} to determine full path
target_link_libraries(myproject ... boost_regex ...)
This seems to work fine.
As for the GLES2 issues I'm using what I placed in the question's comments:
# GLESv2
find_path(GLES2_INCLUDE_DIR GLES2/gl2.h
HINTS ${ANDROID_NDK})
find_library(GLES2_LIBRARY libGLESv2.so
HINTS ${GLES2_INCLUDE_DIR}/../lib)
target_include_directories(myproject PUBLIC ${GLES2_INCLUDE_DIR})
target_link_libraries(myproject ... ${GLES2_LIBRARY} ...)
I have been trying to compile/link/run an Android project that uses the NDK, and has 2 stages of NDK compilation. I have been able to compile using GNU-libstdc++ without including CryptoPP, a great alternative to the OpenSSL libraries for encryption. With CryptoPP, I receive the runtime error noted in the Title.
When compiling my Android NDK project, I have no compiler errors, however during runtime, the CryptoPP library is having trouble locating the symbol "__cxa_end_cleanup". I have tried manually recompiling the libcryptopp.so file using STLport as well as GNU-libstdc++, and both result in the same runtime error. I have been following the instructions per http://www.cryptopp.com/wiki/Android_(Command_Line). I have been properly changing APP_STL when changing compilers.
Looking online, it seems that this error is related to C++ exception handling, and thus I've tried removing the line from Android.mk "LOCAL_CPP_FEATURES += exceptions" so that exceptions are not enabled, but again, same error during runtime.
I am also loading the libraries in the correct, reverse, order in the Java side of the JNI. System.loadLibrary("cryptopp") comes before my other custom-made library is loaded.
I have also tried including the stlport_shared.so in the armeabi/ folder and loading first, before cryptopp, and same error.
Likewise I have tried including the libsupc++.a library in the armeabi/ folder when compiling with GNU-libstdc++, as this is the C++ library that adds exception handling, and have included references to it in Android.mk "LOCAL_CFLAGS += -lsupc++" and "LOCAL_WHOLE_STATIC_LIBRARIES := libsupc++.a"
Has anyone had similar problems using CryptoPP with Android? And if so, how did you configure your makefiles to properly link the libraries? Finally, any idea why this is not causing an error during compilation, and only during runtime? The full error is pasted below:
E/dalvikvm(15888): dlopen("/data/app-lib/com.example.test_app/libcryptopp.so") failed: dlopen failed: cannot locate symbol "__cxa_end_cleanup" referenced by "libcryptopp.so"...
Hi I met the same issue while using NDK and STL, and I've solved it just now. I found that my native library would depend on STL but Dalvik VM didn't load it from system automatically even I packed it into APK file. Hence I try to load it by myself by adding the line in JAVA file:
System.loadLibrary("stlport_shared");
Where my Application.mk looks like:
APP_ABI := armeabi-v7a-hard
APP_STL := stlport_shared
Perhaps it would help to you
I am building an Android native application that uses OpenAL Soft for Android. Everything builds nicely, resulting in two shared libraries in my libs folder: libdig.so (mine) and libopenal.so (the OpenAL library).
When I try to load libdig.so on the device (using System.loadLibrary( "dig" );), however, the link fails with the message:
java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libopenal.so.1" needed by "libdig.so"; caused by library "libopenal.so.1" not found
Now in some sense the problem is obvious. dlopen is looking for a dependency named libopenal.so.1, but the file actually on the system (copied there by ant install) is libopenal.so: with no .1.
In other words, the libopenal.so library is called just that everywhere, except that somehow, internally, libdig.so references it as libopenal.so.1.
Also relevant: When building libopenal, the actual shared library name is libopenal.so.1.13.0, with two symlinks: libopenal.so.1 and libopenal.so. But nowhere is the .1 version referenced: not in Application.mk, or Android.mk, not in the output libs/, or anywhere else.
Android.mk links the libraries thus:
include $(CLEAR_VARS)
LOCAL_MODULE := openal
LOCAL_SRC_FILES := ../../../Fresh/lib/openal-soft-android-master/libs/$(TARGET_ARCH_ABI)/libopenal.so
LOCAL_EXPORT_C_INCLUDES := $(BASE_PATH)/Fresh/lib/openal-soft-android-master/include
include $(PREBUILT_SHARED_LIBRARY)
...
LOCAL_SHARED_LIBRARIES += openal
Now, what is interesting is that if I literally delete the libopenal.so.1 symlink from my system, ndk-build will fail, complaining:
No rule to make target `openal-soft-android-master/libs/armeabi-v7a/libopenal.so', needed by `obj/local/armeabi-v7a/libopenal.so'.
This implies that internally, ndk-build is trying to reference the .1 symlink, even though it's never named and the output file will be libopenal.so.
I am not familiar enough with UNIX or Android development to really understand the purpose of the .1 symlink, so I don't know why there would be this secret reference to that file.
Has anyone encountered this problem? Or do you understand something deeper down about the compilation or management of shared libraries that would explain why libdig.so is referencing a (slightly) wrongly-named library, or how to change it?
I know this question is a couple of years old, but I recently ran into the exact same problem while re-porting my game to Android. This problem frustrated me, and I even tried Alex's link above, only to find I had the same problem. After spending days researching this problem, I came to the following conclusion based on a similar problem someone else had in a forum. The .1 at the end is generally a sign of either using a library that was not built for your target platform (in this case, Android, obviously) or an incorrectly built library altogether.
If you want a quick fix to get around this (without statically compiling OpenAL-Soft into your app while forcing your entire project to be subject to the LGPL), you can simply download some prebuilt libraries from SFML's github page here... that's what I did anyway. You don't have to replace the .a files if you don't need to. Builds for arm, armv7, x86 and mips are in their respective folders.
Hope this helps either the OP or someone else in the future.
The easiest way out would be to use the static library for OpenAL. You can find the prebuilt static libraries in the same ZIP file as the shared libraries.
using openal-soft distrib or git
edit openal-soft/build/CMakeFiles/openal.dir/link.txt
remove '-Wl,-soname,libopenal.so.1'
and rebuild the lib
I've looked thru a lot of material on Android NDK and STLport. I have complex app, java+native code, which loads STLport (a c++ standard library port). The original codebase had "APP_STL := stlport_static" in the Application.mk in the project's "jni" subdir. Causes ld to load the lib static. This caused many compile failures, in current SDK/NDK.
Tried to load as a dynamic lib, as per a suggestion. (In "../jni/Application.mk", set "APP_STL := stlport_shared") With this, I get a clean compile, and load, and the app runs flawlessly on the Android armeabi-v7a emulator, if I disable checkJNI on the "dalvik" virtual machine.
But once I enable checkJNI, I get an "unsatisfiedLinkError" on the libapplication.so, which looks like it might result from STLport being dynamically loaded. So, I want to load STLport in static mode (logcat reports this after several other libs successfully loaded). During the build, compile is ok, but I am getting two multiple definition errors, specifically: "multiple definition of 'vtable for std::bad_exception' " and of 'std::exception::~exception()'. (I have also tried using "gnustl_static").
I am using gcc version 4.3.0 and make version 3.81, command line mode, and small wrapper around build-ndk, for android ndk-r9c, with a build target version of android-8, "ant" to build the .apk file, and so on.
Someone who has more familiarity with Android than me (I am a complete noob) might have seen this before. If so, please advise. Thanx. - Rus
It's definitely possible to use stlport_static with NDK r9c. What object files are mentioned with multiple definition errors? Maybe, you are using some prebuilt libraries? Maybe, the gcc version 4.3 is problematic? Why don't you use the default (gcc 4.8)?
With that, the NDK document explicitly encourages use of shared STL, but you must not forget to call System.loadLibrary() in correct order:
System.loadLibrary("stlport_shared");
System.loadLibrary("Rusfuture");
I am trying to write a simple Android application using the NDK and C++. Specifically, I'd like to use the gnustdc++ included with the newest version of the NDK (r7). The JNI library has compiled and worked perfectly fine as C, but now that I'm trying to introduce C++, I've run into some issues.
I have added ${NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/include/ to my project's include paths, and the #includes inline are resolved. However, attempting to actually use any STL class (such as vector) results in Symbol 'vector' could not be resolved.
All of the standard C symbols imported from <stdlib.h> and such work as well, until I try to replace the #include with <cstdlib>. Then it fails with Function 'malloc' could not be resolved and so forth.
Oddly enough, adding the stlport headers (in ${NDK_ROOT}/sources/cxx-stl/stlport/stlport) fixes all of my issues. However I am linking in GNU C++, not STLPort, so this is an inconvenient and improper "solution" at best. It seems odd that these headers would work but the others would not. Is Eclipse failing to index or resolve the GNU C++ headers?
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libfoobar-jni
LOCAL_SRC_FILES := foobar.cpp
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_C_INCLUDES := sources/cxx-stl/gnu-libstdc++/include/
LOCAL_CFLAGS := -g -std=c99
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := gnustl_shared
Edit: I set up my project based on:
http://mhandroid.wordpress.com/2011/01/23/using-eclipse-for-android-cc-development/
Read this, it has the solution:
http://comments.gmane.org/gmane.comp.handhelds.android.ndk/14371
The summary, in case the link dies some day is this:
It's a bug in the gnustl_shared module declaration. Sorry about that, it will be fixed in the next release.
In the meantime, you can manually change $NDK/sources/cxx-stl/gnu-libstdc++/Android.mk and replace the line that says:
LOCAL_EXPORT_LDLIBS := $(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libsupc++.a
with:
LOCAL_EXPORT_LDLIBS := $(call host-path,$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libsupc++.a)
I know it's not a perfect solution, but at least it'll let you click "run" or "debug" through Eclipse:
Right click on your Android C++ project and select Properties.
Under C/C++ General, click "Code Analysis"
Switch to "Use project settings"
Switch any errors you're receiving due to using the vector class to be "warnings".
For me, the errors I've needed to switch so far are:
"Symbol is not resolved"
"Member declaration not found"
"Invalid template argument"
"Invalid arguments"
"Method cannot be resolved"
Like I said, it's not perfect and you might miss real errors due to this, but you still get the ability to usually select "Go To Declaration" and some syntax checking abilities, as well as the ability to launch your program. The ndk-build step will catch any real errors anyway, so it's really not a huge loss.
Honestly, I'm not sure of the source of this issue. It's likely got to be an Eclipse bug.
Off topic but relevant: you can also use the ndk-gdb through eclipse. The tutorial is on the blog linked to the OP, but here's a direct link anyway.
Best of luck!
Edit (followup):
I've since figured out a way to get around this problem, at least on my box. The OP said that including the STLPORT headers worked for him. It didn't for me, at first. I had to destroy my Eclipse project and start fresh (for some reason, it wouldn't let me remove some include definitions). Adding STLPORT fixed some issues, but in ndk r7b, I was still getting weird errors (e.g. NULL was not defined even after including stddef). I ended up having to include the x86 headers too. These should largely overlap with the arm ones, however, it's useful to have the arm ones 'on top' in the include order.
So, if you've been running into the same issue as I was, add
$NDK_DIR/platforms/android-14/arch-x86/usr/include
to your list of eclipse includes as well.
I had this issue come up on windows due to the different path formats in cygwin, my prefered windows shell, and which uses pseudo unix style paths rather than windows. If you are having this problem, and you have cygwin floating around in your path, eclipse could be using it. Change the paths in Properties>C General>Paths and Symbols to be cygwin style rather than windows style (/cygwin/c/Android.... rather than C:\Android...) ... anyway, this worked for me.