5

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
solidak
  • 5,033
  • 3
  • 31
  • 33
  • See https://developer.android.com/ndk/guides/cpp-support#one_stl_per_app – Michael Sep 18 '18 at 14:11
  • Also keep in mind that the GnuSTL is deprecated and will be removed from the NDK starting with r18. If you want to support both libc++ and gnustl for the time being, the solution is probably to provide two variants of your library. – Michael Sep 18 '18 at 14:12
  • Hey @Michael, I read that page. I understand the part about 'static' linking, but it doesn't mention anything about the `shared` runtime state. The only one I found with relevancy to the issue is this old document: https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/CPLUSPLUS-SUPPORT.html – solidak Sep 18 '18 at 14:15
  • The _"One STL Per App"_ section of that page does not mention static linking, so I interpret that section as being universally applicable, regardless of whether static or dynamic linking of the STL is used. – Michael Sep 18 '18 at 14:17
  • So how can a 3rd-party library make sure that it does not create an extra STL (static), nor does it use an STL that is non-conforming to the environment of the app? I believe Facebook's Yoga simply has a `c++_static` runtime and assumes everyone will use `c++` runtimes – solidak Sep 18 '18 at 14:27
  • static: no need to worry about anything else as everything is linked to your own shared libs. shared: the tool chain will find the version you are linking against and get it packed together with your own shared lib into your apk; as for "whether you native code is used by app directly": as you are building for Java lib, the native code should only be used for your own local java files -- local to your jar module only. All your clients should use Java Interface, not native part. Otherwise it is too messy. – Gerry Sep 18 '18 at 14:33

1 Answers1

7

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.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    Thank for the answer Mr. Cohn. I agree with you about communication, which luckily for me will not occur. For future clarity, I'll link an extra answer I received from one of the maintainers of NDK: https://github.com/android-ndk/ndk/issues/796#issuecomment-422560209 In short, his opinion was to use `c++_shared` after r16 since gnu_stl (both static and shared) are deprecated. There 'might' be issues regarding mangled names if the user has more than one STL. So, if the lib does not communicate with other libraries, it should be safer to use `c++_static` as you mentioned. – solidak Sep 19 '18 at 07:44
  • This issue was very confusing for me, so I'll definitely try to make a small writeup and link it here and I'll be sure to mention your name. Thanks again Mr. Cohn. – solidak Sep 19 '18 at 07:45