Android NDK 23编译C++库时libc++、libc++_shared与libstdc++相关疑问
Android NDK 23 C++库构建相关问题解答
基础配置与复现流程
工程代码
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; }
构建指令
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
验证结果
readelf动态依赖输出
$ 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]
符号查询输出
$ 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' $
核心问题解答
- 问:预期链接
libc++.so实际依赖libc++_shared.so,二者有什么区别?
答:首先你构建时指定了-DANDROID_STL=c++_shared,产物链接libc++_shared.so是符合预期的。二者的核心差异是:Android NDK的命名规则和桌面端LLVM不同,系统分区内置的、专供系统框架使用的LLVM libc动态库命名为libc++.so,NDK不会开放给第三方APP链接使用;NDK提供给开发者的动态版LLVM libc命名为libc++_shared.so,对应的静态版本为libc++.a,这套命名规则是为了避免APP打包运行时和系统自带的libc++.so产生混淆和加载冲突。 - 问:是不是实际使用了libstdc++?
答:没有使用libstdc++。首先你的动态依赖列表里没有任何libstdc相关的库,其次libstdc的标准库符号不会带有__ndk1前缀,你看到的符号特征完全符合NDK版libc++的特征。 - 问:为什么找不到
std::__1前缀的符号?
答:NDK从r18版本开始对自带的LLVM libc做了定制修改,将上游LLVM默认的内联命名空间__1改成了__ndk1,目的是避免NDK编译的产物和其他自带LLVM libc的第三方库产生符号冲突,你在产物中看到std::__ndk1前缀属于正常现象,符合NDK的设计预期。
内容的提问来源于stack exchange,提问作者Elvis Dukaj
相关产品推荐
相关产品推荐

