Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android NDK STL c++_shared w/LIBCXX_FORCE_REBUILD results in std::stringstream NOP

Tags:

tl;dr: The question is for an explanation for why std::stringstream "fails", and why it fails in the way it does (by simply doing nothing), when linking to a rebuilt c++_shared library.

A minimal example:

std::stringstream ss; ss << "Hello World"; __android_log_print(ANDROID_LOG_INFO,                    "APP",                    "Length: %i", ss.str().size()); 

When compiling the project with

APP_STL := c++_shared LIBCXX_FORCE_REBUILD := true 

The output is Length: 0. When using APP_STL := c++_static or LIBCXX_FORCE_REBUILD := false, the stringstream works as expected, with Length: 11 as output.

I'm using many parts of the STL, and the only noticeable difference I've seen so far is this silent NOP stringstream. I've also tested this by modifying the libgl2jni NDK sample, adding the Application.mk file as:

NDK_TOOLCHAIN_VERSION := 4.8 APP_OPTIM := release APP_STL := c++_shared APP_ABI := armeabi-v7a #armeabi-v7a x86 APP_PLATFORM := android-19 LIBCXX_FORCE_REBUILD := true 

I've tested the various permutations of APP_OPTIM as release/debug, APP_STL as c++_shared/c++_static, and LIBCXX_FORCE_REBUILD as true/false, on a Nexus-4, with both armeabi and armeabi-v7a as target ABI. This is the result:

|-------------+-----------+----------------------+---------+------------------| | ABI         | stl c++_? | LIBCXX_FORCE_REBUILD | optim   | Result           | |-------------+-----------+----------------------+---------+------------------| | armeabi     | static    | true                 | release | OK               | |             | static    | true                 | debug   | OK               | |             | static    | false                | release | BUILD FAILED [1] | |             | static    | false                | debug   | BUILD FAILED [1] | |             | shared    | true                 | release | NOP              | |             | shared    | true                 | debug   | NOP              | |             | shared    | false                | release | OK               | |             | shared    | false                | debug   | OK               | |-------------+-----------+----------------------+---------+------------------| | armeabi-v7a | static    | true                 | release | OK               | |             | static    | true                 | debug   | OK               | |             | static    | false                | release | OK               | |             | static    | false                | debug   | OK               | |             | shared    | true                 | release | NOP              | |             | shared    | true                 | debug   | NOP              | |             | shared    | false                | release | OK               | |             | shared    | false                | debug   | OK               | |-------------+-----------+----------------------+---------+------------------| 

[1] /opt/android-ndk-r9d/sources/cxx-stl/llvm-libc++/libs/armeabi/libc++static.a(ios.o):/tmp/ndk-andrewhsieh/tmp/build-21097/build-libc++/ndk/sources/cxx-stl/llvm-libc++/libcxx/src/ios.cpp:function std::_1::ios_base::xalloc(): error: undefined reference to '__atomic_fetch_add_4'

PS: Make sure to do a ndk-build clean in between these tests.

The question: Could anyone give some insight into why std::stringstream fails given these circumstances, and why it fails by just doing a NOP on any data that is streamed to it?

Thanks

like image 653
swalog Avatar asked Apr 13 '14 10:04

swalog


2 Answers

I can't answer why the NOP is occurring in some permutations. But I did manage to find out about the build failures.

I was in a worse situation than you. I was experiencing the build failures relating to the combination of using c++_static and the default value for LIBCXX_FORCE_REBUILD (false) and had no idea why.

Thanks to you for sharing your research into the various permutations of linking STL - I was able to jump straight to the salient documentation to fix the build error.

It's likely that you need libatomic if you #include . Add "LOCAL_LDLIBS += -latomic" for ndk-build

To be able to use libatomic you need to set your NDK_TOOLCHAIN_VERSION to 4.8

like image 132
Cliff Avatar answered Oct 29 '22 06:10

Cliff


Please try this:

LOCAL_LDFLAGS += -Wl,--gc-sections 

It seems that the code snippet doesn't really called atomic_fetch_add(). With --gc-sections LD option, the linker will eliminate the unused code and data from the final executable or shared library. So that the dependency of atomic_fetch_add() is likely to be removed.

Description of "--gc-sections": https://gcc.gnu.org/onlinedocs/gnat_ugn/Compilation-options.html

Some other infomation: https://code.google.com/p/android/issues/detail?id=68779

like image 20
foqq Avatar answered Oct 29 '22 08:10

foqq