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
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 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.
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");
My Android application (game) uses native C++ code for certain operations. That is, I use the Android NDK. The native C++ code is compiled for armeabi only (to the default, armeabi-v5).
The last time I built my c++ code into nativestuff.so was a few months ago, in another computer (Windows 7 + cygwin, because cygwin is recommended for compiling with Android NDK).
I just installed the NDK on my current PC (Windows 7), along with the newest cygwin, and rebuilt the c++ code for my app.
To my surprise, it generates an .so file of 14KB, while the previous .so file was 37KB. Note that the c++ source files are exactly the same (they haven't changed for a year), my project is under version control, so I'm 100% sure.
I tested the c++ functionality in the game, and it works exactly as before, without any bugs.
My C++ files use only cstring.h and jni.h as includes. My Android.mk is as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativestuff
LOCAL_SRC_FILES := nativestuff.cpp
include $(BUILD_SHARED_LIBRARY)
Any idea why the drastic change in .so filesize?
(I added the linux tag as well to this question, because maybe it's a general thing so I want to make sure that linux gurus also check it.)
Run objdump -x file.so on both versions. This will list all the sections and their sizes. That should give you a clue as to where the problem lies. (i.e. is there a new .debug section that's 23KB long? Maybe debug mode got enabled.)
If your code sections are radically different, compare the output of objdump -d file.so. Maybe your compiler automatically inlined more code, which saved a lot of space.
If another section is new/different, post the output in another SO question.
Maybe the previous .so was generated with debugging information.
(compiled with gcc -g option)
You may try one thing: use the command size executable-name. That will give you size of the different areas of your executable code. If the previous build is available do the same to that. You may get an idea where the change is.
The thing that I am trying to do is to use the android's openssl libraries so I would like to add the library at some other embedded applications and just keep the data encrypted. I tried this things on the cyanogen 7.1 platform by just adding:
LOCAL_C_INCLUDES += /external/openssl/include
LOCAL_SHARED_LIBRARIES += libssl libcrypto
in the Android.mk file of the current project and I was able to use all functions with a simple #include in the particular .c file.
Alas, all this does not work just as straightforward on cyanogen 9 and I am looking for some help. Could you please tell me if there is something changed in the build system or something else that I need to do?
For example I have errors of this kind:
undefined reference to EVP_get_cipherbyname'
undefined reference toOPENSSL_add_all_algorithms_noconf'.
I would just like to repeat that I port all the code and all the things that I did on cyanogen 7 (and worked flawlessly) to cyanogen 9 and I can not build the platform. I am sure that I have all the includes and everything is fine with the .h files. In my opinion, it is just the linking of the libraries that possibly could cause the problem.
Any help is greatly appreciated.
It seemed that you need to add both the C includes and the libssl and libcrypto libraries in all 3 implementations of the sqlite located in the Android.mk file. That would be one implementation of the sqlite used by the android applications, and two sqlite implementations that are generated in the android platform.