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?
Related
I'm compiling a 3rd-party Java library for Android that uses JNI. I read the relevant pages on adding C++ support on developer.android but I'm still confused about a couple of issues regarding C++ STL runtime that I was hoping I could clear up here:
1- My library has no control over the app it will be embedded in, so I don't know if there will be other libraries that might use a static/shared STLs. If I use a static C++ runtime with ANDROID_STL=c++_static, is it safe, or should I have to worry about another library that could be using something like gnustl_static which might conflict with mine?
2- If I use a shared C++ runtime with ANDROID_STL=c++_shared, is it a guarantee that a specific element in the STL will use the libc++ runtime or could it be possible to use gnustl if it doesn't exist? For example, If I was using std::string with a shared c++ runtime (c++_shared) in an app that has another library of gnustl_static, will my std::string implementation be taken from libc++ or gnustl?
Ideally, I'd like to have a very stripped down version of a static c++ runtime with (c++_static) that only includes std::vector, std::string and std::map. I was actually planning to use something like -ffunction-sections as described here and #768.
Please advise and thank you.
Environment Details
Pkg.Desc = Android NDK
Pkg.Revision = r15c
Android Studio = 3.1.2
system: cmake Host OS: Arch Linux ($ uname -r % 4.18.5-arch1-1-ARCH)
Compiler: Clang++
STL: c++_static/c++_shared
Your concern is a very real one. But if handled properly, you can find a robust way out.
The warnings about using single C++ runtime across all libraries in the app (and the whole idea to define C++ support in NDK as APP_STL vs. most other flags such as LOCAL_CFLAGS or LOCAL_SHARED_LIBRARIES, are relevant for the native libraries that are connected. JNI libraries that never communicate directly (except through their corresponding Java layers) can use different C++ runtimes. Another point is that normal build will only package one C++ runtime shared lib into the APK. Note that versioning is also a potential hazard: if a developer who adds your library uses a different NDK release, there might be collisions or unexpected side effects when his version of STL runtime works with your code.
Therefore, to achieve maximum flexibility, your library should use a static C++ runtime. This may effect the size of the binary, but if, as you say, you use only a limited subset of STL, this extra will be rather small.
The bottom line, you will have minimum to worry about if build your shared library with libc++_static.
There's many shared libs(*.so) in my android project. Some of them were built by others, I don't have the source code.
I'm using NDK r10e, and I want to upgrade the NDK version to r13b.
If I don't change the makefile, just build part of the shared libs with NDK-r13b, others built with NDK-r10e were not changed. Is there any problem with capability of the android program?
NDK-r10e use clang-3.5
NDK-r13b use clang-3.8
following configurations are the same:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-19
APP_STL := gnustl_shared
It's generally a good idea, but isn't always required. We try to preserve compatibility across NDK versions since, yes, moving across a compatibility boundary is difficult when you don't have the source to your dependencies, but sometimes bugs can't be fixed without breaking compatibility.
It's generally a good idea because doing so will have the least surprises. We only ever test a version of the NDK against itself. It will also save you a lot of time trying to figure what went wrong when there are compatibility breaks.
A couple examples (by no means a complete list) of things that can go wrong:
The public API surface of the NDK has changed over time. The APIs still exist on the device so that legacy apps continue working, but sometimes APIs are removed from the NDK so that new apps don't use them (there are a handful of reasons this might happen). In these cases, an old library that uses a removed symbol won't be able to be linked against a new library/executable using an NDK that doesn't have those APIs (this actually depends on the behavior of the linker; it's always true for static libraries, I think it's only arm64 for shared libraries).
For upgrading from r10 in particular, there was an ABI break in libc++ (required to avoid nasty interactions with the system) that means that libraries built with r10 and libraries built with r11+ are not compatible. You're using gnustl, so that problem won't affect you, but it's worth mentioning for others that land here.
We have an Android application with several native libraries. Currently, most of them use stlport_shared, but we are interested in upgrading to c++_shared (the LLVM libc++ runtime). If we were to upgrade some of them, but not others, we would have to load both stlport and llvm.
I imagined that loading two implementations of the STL might cause issues, but in practice the app seems to run correctly. Is this undefined behavior, or is it allowable to load more than one STL implementation?
I've read over https://developer.android.com/ndk/guides/cpp-support.html and some of the documentation supplied with the NDK, but can't seem to find a definitive answer. Thank you for your help!
It's best to avoid this if at all possible.
If an STL type (like a std::string, for example) is accessed by both an stlport_shared binary and a c++_static binary, as the two implementations of std::string are not compatible this will not work.
You also are vulnerable to the issues described by https://stackoverflow.com/a/25856207/632035
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).
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");