Home > Mobile >  Confustion about Android NDK libc libc _shared, libstdc
Confustion about Android NDK libc libc _shared, libstdc

Time:11-30

I am getting very confused trying to build a simple C library using Android NDK 23 (23.1.7779620). I am using CMake and this is a very simple program:

CMakeLists.txt:

cmake_minimum_required(VERSION 3.14)
project(mf) 
add_library(mf lib.cpp)

lib.hpp:

#pragma once
#include <string>
std::string foo(std::string);

lib.cpp:

#include "lib.hpp"

std::string foo(std::string str) {
  return std::string{"test"}   str;
}

This is the command line to build:

cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DANDROID_STL=c  _shared -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=android-29  -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake .. 
cmake --build . -v
  • The first problem is that I was expecting to link against libc .so and not libc _shared.so. What is the difference between them? I read this article. But still is not explained the difference betweend libc and libc _shared
  • The second problem is even worst, it seems I am using libstdc !
  • The 3rd point, I was thinking that the c implementation of clang was under the namespace std::__1 but I cannot find anything like that.

I know libc _shared is used because of this command:

$ readelf -d libmf.so

Dynamic section at offset 0x76e0 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc  _shared.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libmf.so]

Running nm it seem I am using symbols from libstdc :

$ nm -gDC libmf.so | grep '__ndk1'
0000000000003af0 T foo(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >)
                 U std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::append(char const*, unsigned long)
$ nm -gDC libmf.so | grep '__1'
$

CodePudding user response:

By passing -DANDROID_STL=c _shared to the CMake invocation you explicitly asked for the shared runtime as opposed to the default runtime.

As explained in the documentation, the rules are simple:

  1. if all your native code is in a single library, use the static libc (the default) such that unused code can be removed and you have the smallest possible application package.
  2. As soon as you include an extra library – either because you include a precompiled library from somewhere else or you include an Android AAR file that happens to include native code – you must switch to the shared runtime.

The rationale for the rules is simple: the C runtime has certain global data structures that must be initialized once and must only exist once in memory. If you were accidentally to load two libraries that both link the C runtime statically, you have (for instance) two conflicting memory allocators. This will result in crashes when you free or delete memory allocated by the other library, or if you pass a C STL object like std::string across library boundaries.

For completeness, in older NDKs libstdc (the GNU C runtime) was also included in the NDK, but as of NDK r18 that is no longer the case.

  • Related