在Linux环境下如何消减可执行文件或者动态库的大小

举报
JackieAtHome 发表于 2020/06/05 23:29:11 2020/06/05
【摘要】 在硬盘空间受限的场景下,如果对动态库瘦身?

为了简化描述,下文提到目标时,如无特殊说明,均指代目标可执行文件或者目标动态库。

操作步骤如下:

  • 选型时,在同等功能时,尽量选择代码量少、占用空间小的开源的软件。

  • 控制C++特性的使用,如无必要,则不使用C++的高级特性。

    • 屏蔽RTTI特性,增加编译选项-fno-rtti

    • 屏蔽异常我,增加编译选项-fno-exceptions

  • 对性能影响不大时,避免使用C++的inline特性。

    • 增加编译选项-fno-inline

  • 在不影响使用时,控制对STL的组件的使用。

  • 避免使用STL的iostream的相关模板类。

  • 构建目标动态库时,控制符号的可见性。

    • 增加编译选项-fvisibility=hidden

    • 增加编译选项-fvisibility-inlines-hidden

    • 定义符号导出宏,如下代码。

      #ifndef __has_attribute
        #define __has_attribute(x) 0#endif#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility)
        #define MY_EXPORT     __attribute__((visibility("default")))
        #define MY_IMPORT     __attribute__((visibility("default")))#else
        #define MY_EXPORT
        #define MY_IMPORT#endif// 在外部可见的符号上,使用上述宏修饰。MY_EXPORT int foo(int a, int b);
  • 对目标以及全部依赖,使用gc-sections特性。即:

    • 编译源码时,增加选项-ffunction-sections -fdata-sections

    • 链接目标时,增加选项-Wl,--gc-sections

    • 链接目标时,增加选项-Wl,--icf=safe

  • 对目标以及全部依赖,使用LTO特性。

    • 编译源码时,增加选项-flto=full

    • 链接目标时,增加选项-flto=full

  • 构建目标时的外部依赖,均使用静态链接。比如:

    • 静态链接STL库。

    • 静态链接使用前述要求编译的依赖库。

  • 构建目标时,要求编译器对目标占用的空间进行优化。

    • 增加选项-Os

    • 假如链接失败,则修改为-O2

  • 链接时,对于Release版本,删除不必要的调试符号。

    • 增加选项-s

如下使用CMake的请求,描述选项。

# 关闭C++特性set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-inline")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")# 控制符号的可见性set(CMAKE_C_FLAGS_RELEASE     "${CMAKE_C_FLAGS_RELEASE}   -fvisibility=hidden")set(CMAKE_CXX_FLAGS_RELEASE   "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility=hidden")set(CMAKE_C_FLAGS_RELEASE     "${CMAKE_C_FLAGS_RELEASE}   -fvisibility-inlines-hidden")set(CMAKE_CXX_FLAGS_RELEASE   "${CMAKE_CXX_FLAGS_RELEASE} -fvisibility-inlines-hidden")# 删除调试符号set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")# 开启空间优化if (APPLE)  set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Oz")  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Oz")else ()  set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")  set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os")
endif ()# 使用gc-section优化set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ffunction-sections -fdata-sections")set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_EXE_LINKER_FLAGS}    -Wl,--gc-sections")set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--gc-sections")set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")# 使用icf优化set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_EXE_LINKER_FLAGS}    -Wl,--icf=safe")set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--icf=safe")set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--icf=safe")# 使用LTOset(CMAKE_C_FLAGS_RELEASE     "${CMAKE_C_FLAGS_RELEASE}     -flto=full")set(CMAKE_CXX_FLAGS_RELEASE   "${CMAKE_CXX_FLAGS_RELEASE}   -flto=full")set(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_EXE_LINKER_FLAGS}    -flto=full")set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flto=full")set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flto=full")

参考资料



若非注明,均为原创,欢迎转载,转载请注明来源:在Linux环境下如何消减可执行文件或者动态库的大小

链接地址:http://www.jackieathome.net/archives/777.html


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。