【问题标题】:Android NDK produce massive .so file which has only one functionAndroid NDK 生成海量 .so 文件,只有一个功能
【发布时间】:2019-04-16 06:34:55
【问题描述】:

当使用 android NDK 构建这个 cpp 文件时,我得到 800KB .so 文件:

test.cpp

int *test() {
    return new int;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
set(SOURCE_FILES test.cpp)
add_library(native_util SHARED ${SOURCE_FILES})

这对我来说是不可接受的尺寸。如果这有什么问题,请纠正我。


我刚刚意识到,当我删除 test.cpp 中的 new int 时,.so 文件大小减少到 80KB...嗯,怎么可能???

test.cpp 生成 80KB .so 文件

int test() {
    return 0;
}

我的 NDK 版本:

Android/sdk/ndk-bundle 
➜ cat source.properties 
Pkg.Desc = Android NDK
Pkg.Revision = 19.2.5345600

【问题讨论】:

    标签: android c++ android-ndk


    【解决方案1】:

    简单来说,取决于共享库中包含多少所需的外部符号。

    当我删除 test.cpp 中的新 int 时,我才意识到,然后 .so 文件大小减少到 80KB...嗯,怎么可能???

    这是可能的。因为,下面的代码

    // test.cpp
    int *test() {
        return new int;
    }
    

    new 运算符依赖于其他 C++ 库,当您构建 test.cpp 时,共享库,例如test_with_new_operator.so 文件将添加这些外部符号信息以供将来在链接阶段使用,例如std::xxx 需要的符号。当您将其更改为

    // test.cpp which produce 80KB .so file
    int test() {
        return 0;
    }
    

    它不依赖于 C++ 标准库,并且这些符号信息不会添加到您的 test_without_new_operator.so 中,您会看到更小的尺寸。

    例如,当你发出命令时

    nm --demangle ./libs/armeabi-v7a/libnative-lib.so
    

    test_with_new_operator.so 包含以下符号信息(更多外部符号信息!!!

    0001ba44 r GCC_except_table0
    0001b668 r GCC_except_table0
    0001b698 r GCC_except_table1
    0001ba98 r GCC_except_table1
    0001b568 r GCC_except_table1
    0001b9b8 r GCC_except_table1
    ...
    0000622c T std::bad_array_length::bad_array_length()
    0000623c T std::bad_array_length::~bad_array_length()
    000061c8 T std::bad_array_length::~bad_array_length()
    000061c8 T std::bad_array_length::~bad_array_length()
    ...
    00017222 t std::__ndk1::__vector_base<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, __cxxabiv1::(anonymous namespace)::short_alloc<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, 4096u> >::~__vector_base()
    0001867a t std::__ndk1::__vector_base<std::__ndk1::vector<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, __cxxabiv1::(anonymous namespace)::short_alloc<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, 4096u> >, __cxxabiv1::(anonymous namespace)::short_alloc<std::__ndk1::vector<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, __cxxabiv1::(anonymous namespace)::short_alloc<std::__ndk1::vector<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, __cxxabiv1::(anonymous namespace)::short_alloc<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, __cxxabiv1::(anonymous namespace)::malloc_alloc<char> > >, 4096u> >, 4096u> >, 4096u> >::~__vector_base()
    0000e304 t std::__ndk1::__split_buffer<__cxxabiv1::(anonymous namespace)::string_pair<std::__ndk1::basic_string<char, 
    ...
    

    但是,test_without_new_operator.so 不会有这些符号,并且库大小更小。


    编辑#1

    这对我来说是不可接受的尺寸。如果这有什么问题,请纠正我。

    这个你不需要太担心,因为当你将那些共享库打包到最终的 apk 中时,不必要的符号和调试信息将被剥离(gradle task app:transformNativeLibsWithStripDebugSymbolForRelease 将完成这项工作)并且你的最终apk 大小实际上比您无法接受的要小得多。

    此外,如果您有兴趣,请交叉检查以下参考资料:

    【讨论】:

    • 是的,打包在release apk中的.so文件只有100KB(压缩后的大小~40KB)
    猜你喜欢
    • 2015-03-02
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    相关资源
    最近更新 更多