Forcing ndk-build to include C++ libraries - android

I have an application where all components are first assembled as static libraries and then those libraries are repacked to shared libraries. So the module(s) doing include $(BUILD_SHARED_LIBRARY) have empty LOCAL_SRC_FILES. With the way the components are laid out and composed, it makes sense and must remain that way.
However, the library for APP_STL only gets added if there is a C++ source (recognized by extension, which can be overridden with LOCAL_CPP_EXTENSION) in LOCAL_SRC_FILES. So the standard library does not get added and the final object does not link, because the component libraries do need it.
Is there a way to force NDK to include it?

There is an undocumented variable LOCAL_HAS_CPP that does it:
LOCAL_HAS_CPP := true
It is relatively new though. It is in the most recent NDK r16b (as of Mar 2018), but not in the r12b version we used until now.

Related

Using GNU STL and C++11 with V8 on Android NDK

I am building an application on Android using NDK and V8. I would prefer to use C++11 and GNU STL for features such as shared_ptr; however, the V8 build system seems to be hardcoded to use stlport_static as its STL variant.
Even when patching the build system to generate a fully self-contained library, V8's build does not statically link STLport into its .a files (which is to be expected), and thus I get hundreds of linker errors from unresolved symbols in libv8_base.a et al. I also do not see any way to indicate to ndk-build that it should link in stlport_static when I am using a different STL variant.
Is there a reasonable pattern to linking in stlport_static while using gnustl_static, or, better yet, is there a way of building Android V8 against gnustl_static instead?
You have a problem. Well, mixing different STLs in separate .so's is possible, with extra care; but using two STLs inside one .so is simply impossible.
You either need to implement your own shared_ptr (no big deal), but then you will face the same issue for every other feature that exists in gnustl and not in stlport.
Or you need to port V8 to gnustl (and I am afraid that the MIT license does not allow this).

How to statically compile C++ runtime into NDK/JNI library on Android?

I'd like to compile a library (static but also could be shared) written in C++ so that is statically contains all the C++ runtime functionality that I use in the library, i.e. another project can simply include my .a or .so file without having to worry about further dependencies. How can I do this using the NDK/Android build system?
So far, I have
APP_STL := c++_static
in my Application.mk and build my library using
include $(BUILD_STATIC_LIBRARY)
in my Android.mk after setting up the project. However, if I then pull in the resulting library into a second project (say, a dynamic library) that does not specify an STL (e.g. pure C) I get a load of symbol not found linker errors. Only when I specify to use the c++_static STL in the second project do these errors go away indicating that c++_static was not pulled into the first library. (I know this isn't surprising but it's not the behaviour I want).
Using good ol' make files and specifying build flags myself allows me to combine static libraries. My problem is coaxing the NDK build system to do it :)
if you compile a C++ runtime statically to your lib, unfortunately another project have to worry about this dependency:
If several .so files are using static C++ runtimes, this can lead to corruption and crashes because of the sharing of global variables used by the runtimes.
If you compile everything (your lib and the final project) into a single .so file, you can use one static C++ runtime, and it's better then if it's declared inside the end project. Because forcing the static inclusion of the C++ runtime in your lib would prevent the end project of using a C++ runtime.

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

How to build a shared library without JNI in Android?

I develop an Android application, which needs to be a shared library. I have already made the same lib in Linux (using gcc), so I want to compile the same shared lib in Android (ARM processor). But NDK only suports JNI. Now I want to build a separate shared library without direct JNI interaction. I have a lot of C files and headers, so i cannot write JNI for everything. I want build my library for ARM processors. How can i do this?
my stuture is
----->JNI
---->myfile.c(jni c code)
----->android.mk(here i call my two shared lib)
folder1
--->include
----src
---->lib(here i will get my shared lib)
folder 2
----->include
----->src
----->lib(here i will get my 2nd shared lib)
Here I want to build my shared lib separately and then I will call it. Is it possible to build a shred lib without JNI in Android?
Android NDK makes no requirements for JNI compliance of the binaries built with it. But usually Android applications are written in Java, and when they use native components, the natural path is to use JNI.
Android NDK provides a rich and easy to use ndk-build command, which requires you to prepare at least one Android.mk file that is used by their make system. In many cases it is worth the effort to prepare such file based on your makefile(s). But if the project that you port from another platform uses advanced configure or Cmake features, you can skip the Android.mk completely, and use the standalone toolchain which is part of the NDK, as described in NDK official documentation. Note that Android does not support full Linux glibc, but rather a subset called bionic. The STL support is also not obvious, you have to choose one of the 7 options!
You can stop right here, get the shared library or an executable file and use them in traditional Linux manner. You can build your Android application all in C++.
But the easiest approach is to build a Java Android application using Android SDK, and call some native methods via JDK. You will need a wrapper .so for that, a library that exports JNI functions to Java and calls the non-JNI libraries in turn. In Android.mk you can refer to these libraries with LOCAL_SHARED_LIBRARIES. You may find the following question useful for this part: ndk build library outside main project source tree.
You will need to load the native libraries "manually" in your Java code. The system loader only searches for unresolved references in /system/lib folder.
The conventional place is the static constructor of the Java class that uses the native methods. The order of loading is important. If libone.so depends on libtwo.so, and libjni.so depends on libone and on libtwo, you will have something like
{
System.Load("two");
System.Load("one");
System.Load("jni");
}
You should also make sure that the Android SDK builder finds the files in libs/armeabi or libs-armeabi-v7a directory when it creates the APK file.
It is possible to build native library without writing any JNI specific C-code. You need to create Android.mk and Application.mk files for your library. You have a valid makefile ready, so you can use it to make an Android.mk.
Application.mk can be as follows:
APP_OPTIM := release
APP_PLATFORM := android-7
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DANDROID
APP_ABI := armeabi-v7a
APP_MODULES := <put-the-name-of-your-library-here>
Use ndk-build to compile the library.

How to build Android NDK .so without STL?

I'm using the newest Android NDK r6b to build my shared object. This library does not use any kind of STL at all, but resulting .so includes many STL stuff like std::bad_alloc_what(void) and many more, which increases size of binary greatly. Also release builds include this garbage. APP_STL not defined anywhere, also the NDK r5b produces small binary with used functions only. Is it a bug of r6b? How can I build with r6b without STL stuff?
It seems that there is a bug in NDK r6b and it always builds libraries with exceptions support, even if -fno-exceptions is explicitly specified.
See this question for details: Android NDK produce unreasonable big binaries, how to optimize .so size?
If you are using, say, new then you are implicitly using the standard library for the std::bad_alloc exception. Unless you call the no-throw version of new, which would instead use std::nothrow. If you don't use the standard library, then it won't get linked. Just make sure you don't, if that's what you want, or perhaps just move to C?

Categories

Resources