libc++_shared.so
在目前ndk的最新版本25.1.8937393
中有4个libc++_shared.so
,用Everything
搜索结果如下:
可以看到,大小最小的有4M多。
对于libc++
库,官方介绍在此,摘取一些片段如下:
LLVM 的 libc++ 是 C++ 标准库,自 Lollipop 以来 Android 操作系统便一直使用该库,并且从 NDK r18 开始成为 NDK 中唯一可用的 STL。
libc++ 的共享库为 libc++_shared.so,静态库为 libc++_static.a。通常情况下,构建系统将根据用户需要对这些库的使用和打包进行处理。
注意:libc++ 不是系统库。如果您使用 libc++_shared.so,就必须将该库添加到您的应用中。如果您使用 Gradle 构建应用,此步骤会自动完成。
接下来我们来验证一下最后一句话:如果您使用 Gradle 构建应用,此步骤会自动完成。
使用Android Studio的向导创建一个Native C++项目
,自动创建的mative-lib.cpp
文件如下:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_cn_dazhou_hello_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
然后运行到模拟器,然后执行:构建 > Analyze Apk…,然后选择我们的app-debug.apk
进行分析,如下:
如上图所示,产生的libhello.so
大小为114.5KB。这里我们看不到libc++_shared.so
,这是因为CMake
构建工具默认使用c++_static
进行编译的,也就是说会把用到的libc++_shared.so
中的相关内容编译到libhello.so
中,注意,只是编译用到的相关内容而已,这也是为什么libhello.so
只有114.5KB,而libc++_shared.so
有4M以上,我们可以配置CMake
不使用c++_static
,而使用c++_shared
,如下:
plugins {
...
}
android {
...
defaultConfig {
applicationId "cn.dazhou.hello"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
cppFlags '-std=c++17'
}
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.18.1'
}
}
...
}
dependencies {
...
}
关于cmake
的更多参数在此。
这个参数配置的写法我是参考的是这个。
再次运行app,然后再查看apk的分析,如下:
如上图所示,此时就能看到libc++_shared.so
了,大小为370.3KB,而libhello.so
的大小只有17.3KB。
如果应用包括多个共享库,应使用 libc++_shared.so
,比如多个Android库有依赖关系,每个库都使用到了libc++,则应该使用c++_shared
的方式编译,这样 libc++_shared.so
的内容就不会被重复打包到多个so中了。多个库中的 libc++_shared.so
最好保持使用同一个版本,因为最终打包apk时只会选择其中一个 libc++_shared.so
打包到apk中。
在 Android 系统中,NDK 使用的 libc++ 与操作系统的 libc++ 是不同的(也就是说Android系统本身内部就已经有libc++的实现了)。如此一来,即使应用以旧版 Android 为目标平台,NDK 用户也能获得最新的 libc++ 功能和 bug 修复。需要权衡的是,如果使用 libc++_shared.so,就必须将该库添加到您的应用中。如果使用 Gradle 构建应用,此步骤会自动完成。 早期使用ndk-build进行编译的时候,是不会自动使用 libc++_shared.so的,则默认使用的是系统内部自带的libc++库,比如该系统自带的libc++的版本是C++11,而我们写的C++代码使用到了C++17,则此时运行就会报找不到函数实现,所以需要使用ndk中支持c++17版本的libc++_shared.so实现,如果是用ndk-build编译的就需要指定添加该so,如果是使用gradle编译,则会自动使用对应的so,无需要手动设置。