Eclipse-CDT fails to find stdlib symbols in NDK project - android

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.

Related

Undefined Symbol Error for a Header File in Android NDK

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.

Android native library references incorrect shared library

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

Makefile generation tool for Android NDK prebuilt libraries?

I'm doing a little bit of work with the Android NDK, and I'm spending a lot of time hand-editing the makefile for my prebuilt library every time I add or remove a source file. It seems like it should be possible to automate this. Are there any good tools for the job?
I'm a seasoned web/mobile developer but I'm brand new to building from the command line so it's entirely possible I'm overlooking an incredibly obvious right way to do this.
Try something along the lines of:
LOCAL_SRC_FILES := $(wildcard **/*.cpp)
(Assuming .cpp files is all your source.)

Much smaller .so file for identical source code

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.

Official "Boost library" Support for Android and iOS? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
This question is in continuation to Should I choose Boost Asio or Aysnc Socket threads in Android? asked,
Boost libraries are intended to be widely useful, and usable across a broad range of applications, but yet there is no official support available for Android and iOS
Is there any specific reason behind the same like Not optimized for
embedded devices? Or any other reason?
Does any body know of any application built using Boost on Android or iOS?
Is it advisable to use boost libraries for network intense application which spawns multple threads for commuication?
FYI..I have been using following links to create a sample Android application , but not successful yet :(
https://github.com/MysticTreeGames/Boost-for-Android
http://www.codexperiments.com/android/2011/05/tips-tricks-building-boost-with-ndk-r5/
Include Boost C++ library in android
How to use the boost library (including shared_ptr) with the Android NDK and STLport
https://sites.google.com/site/fourdollars/android/android-mk
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/4lxhsKFe7Ho
http://www.crystax.net/trac/ndk/ticket/6
Android NDK R5 and support of C++ exception
Thanks in advance.
Got reply from boost community
Yes. These platforms are not officially supported because no one has
volunteered to run regression tests regularly for them.
It is not possible for a Boost developer to test on all platforms. So
developers depend on the test results of regression tests run by
volunteers. For example, see
http://beta.boost.org/development/tests/trunk/developer/summary.html
If no one volunteers to run the tests for a particular platform, that
platform is not officially supported.
So if you care about Android or iOS becoming officially supported,
start running regular (preferably daily) regression tests for Boost.
See http://beta.boost.org/development/running_regression_tests.html
Check out my cross-platform-tutorial on github. It shows you how to set up Boost and use it between iOS and Android. I had such a horrible time with this, I figure I'd document it so no one else had to figure it out. You'll notice that this project also pulls in several other common items used between the two platforms, e.g., CoreFoundation and SQLite.
https://github.com/markshiz/cross-platform-tutorial
Note: My tutorial does not show how to build the compiled libraries for boost. I have done that before with success using the instructions you provided:
http://www.codexperiments.com/android/2011/05/tips-tricks-building-boost-with-ndk-r5/
After you have a static library compiled by the Android toolchain, you can easily link it in via a module similar to those under the include/[NAME OF NEW SUBMODULE] directory of the project above. Use something similar to the following for the Android.mk file in the root of that directory.
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_regex
LOCAL_SRC_FILES:= ./path/to/built/static/library/libboost_regex-gcc-mt-s.a
LOCAL_EXPORT_C_INCLUDES := ./path/to/the/directory/that/has/the/boost/headers
include $(PREBUILT_STATIC_LIBRARY)
Finally, import that module, as in the example, inside
$(call import-module,[NAME OF NEW SUBMODULE])
As far your other questions --do you know of an application that uses Boost on iOS and Android? Yes, I have done it multiple times with success and released working apps to the App Stores.
Your other question, is it advisable to use boost for network communication? I'm not sure what you mean here. From what angle? Do you mean, philosophically, technically, etc?
Philosophically, you have to ask yourself, what is your reasoning for importing this library and using it between Android and iOS. Is it to save code time, maintenance burden. If so, I'd say this is an excellent way to do that. Clearly there are some hurdles and pain to get this sort of a set up working. Also, the IDE features for C++ aren't as awesome as for Java in Eclipse. I try to be fair and balanced in the PDF presentation in the doc/ directory. Give that a once over.
From a technical perspective, I think the only thing I would be worried about is making sure I clean up the Asio objects properly when the Activity is stopped. If you need to do things in the background, use a Service instead:
http://developer.android.com/reference/android/app/Service.html
UPDATE: There seems to be a problem with std::atomic on Android, and since Boost.Asio is using it (by default), combined with threads, one occasionally got deadlocked. Fortunately Boost.Asio makes it easy to switch from Std.Atomic to Boost.Atomic and this has been taken care of in the Boost-for-Android project in this commit.
For more info about the bug, see here
We are developing a simple multiplayer game (not yet released) for Android using boost asio and so far we did not have any problems. That's for the question #2.
What kind of problems are you seeing?
If the problems are related to compiling and linking, perhaps these hints will prove useful.
Add following to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Have this in your Application.mk file:
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti -fexceptions
And use this as a template for your Android.mk file:
LOCAL_PATH := $(call my-dir)
BOOST_VERSION := 1_49
PROJECT_ROOT := $(LOCAL_PATH)/../../../..
BOOST_INCLUDE_PATH := /path/to/boost/headers
BOOST_LIB_PATH := /path/to/boost/libraries
# Path and name of the STL library. Add this to the *end* of LOCAL_LDLIBS.
# Note this is a hack/workaround to prevent linker errors when compiling with
# boost.
STL_LIBS := -L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/libs/armeabi \
-lgnustl_static
include $(CLEAR_VARS)
LOCAL_MODULE := native-activity
LOCAL_C_INCLUDES:= $(BOOST_INCLUDE_PATH) \
$(PROJECT_ROOT)/src \
$(PROJECT_ROOT)/platform/android/jni
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS := -llog -landroid
# The order of these libraries is often important.
LOCAL_LDLIBS += -L$(BOOST_LIB_PATH) \
-lboost_system-gcc-mt-$(BOOST_VERSION) \
-lboost_thread-gcc-mt-$(BOOST_VERSION) \
$(STL_LIBS)
LOCAL_STATIC_LIBRARIES := android_native_app_glue
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
EDIT: How we build boost for Android. This is what we have in our Makefile:
git clone git://github.com/madadam/Boost-for-Android.git
./build-android.sh --boost=1.49.0 --with-libraries=chrono,program_options,system,thread /path/to/ndk
Note that we are using our own fork of Boost-for-Android, this is only because that one has a patch for the newest NDK version r8d. It can also be seen from the command line that we are using the 1.49 version of boost, this is currently the highest supported by Boost-for-Android.
If you would like to know what combinations of Boost and Android NDK are supported, have a look inside the Boost-for-Android project. It contains directories called patches/boost-<X>/ndk-android<Y> where X corresponds to the supported boost version and Y to the supported NDK version (shameless plug: our 2 cents to the project :-)).
Below are some more (Very useful) information received from boost community:
Is there any specific reason behind the same (like not optimized for
embedded devices)? Or any other reason?
Boost works perfectly on Android. As there is a NDK (native development kit)
with a quite decent gcc (4.6 something) you just need to configure boost build
to use the right gcc. Although this all works, it requires a little bit of
tinkering to get the settings right. But again, in principle, there is not a
lot of difference in building Boost for Android or any other linux
distribution.
Are there (at all) any known issues if we use boost libraries for
networking and thread synchronization for Smartphone application
development ? Will it be a good idea to use BOOST ASIO for the same?
It is perfectly fine to use Boost.Thread or Boost.Asio. They work perfectly fine
on ARM devices. There is even support for the more platform specific hackeries
like boost.atomic and boost.context.
FYI are the links found
https://github.com/MysticTreeGames/Boost-for-Android
http://www.codexperiments.com/android/2011/05/tips-tricks-building-boost-with-ndk-r5/
Building boost with the Android NDK is even simpler than with boost.build
directly. I compiled a bunch of Android build scripts, which can be found
here:
https://github.com/STEllAR-GROUP/HPXAndroid/tree/master/modules
Look for the boost_${module} for various boost libraries. This is not a
complete list. Only what i needed. Also, might need some love for 1.53.
All the different libraries didn't need any special android treatment (modulo
some minor bugs where the compiler didn't agree with other gcc versions)
I hope this would be useful for others as well!
Thanks!

Categories

Resources