Linux编译时如何减小so库文件的大小

Linux编译时如何减小so库文件的大小

     今天问了我这个问题,我就顺便记录一下。客户问为什么libc.so文件再编译前和编译后的size不一样啊,staging 和 compile 两个dir下的 libc.so大小不一样,具体有什么区别吗?

      这是是因为编译的时候还会用strip工具来处理库文件,把二进制文件中的包含的符号表和调试信息删除掉,所以库文件编译打包后会变小。

Strip工具是什么?

    在linux下有个工具叫做strip,这是一个可以将linux下的可执行文件的符号表去除,减少每个可执行文件的大小,这对于嵌入式方面很有必要。但是没有了符号表也就意味着没有办法采用gdb进行调试,因为gdb调试是读取ELF文件头来获取符号表,方便调试,但strip之后,可执行文件的ELF文件头就没有.symtab这个符号表,有的仅是动态符号表。在strip之后nm libxxx.so是看不到符号表的,nm -D libxxx.so可以看到动态符号表,但用处不大,但strip有个参数选项叫做--only-keep-debug,这个选项可以在strip的时候保留debug调试信息。

    strip命令如何使用,可以自行搜索一下。

那我们再把问题拓展下:Linux编译时如何减小so动态库文件的大小

参考https://www.cnblogs.com/yuwl26/p/13604529.html

在一些嵌入式系统开发中,由于成本和资源的限制需要对动态库的大小进行限制,主要通过以下几种方法:

1. 编译选项使用-Os,编译优化;

2. 去掉-g选项,去除调试信息;

3. 通过strip工具裁剪符号及调试信息;

4. 只导出必要符号;Linux会默认导出所有符号,并不仅仅导出你开放的接口!

 

C++的还可以参照这里:

在Linux环境下编译如何减小可执行文件或者动态库的大小(C++)

转博文:http://www.jackieathome.net/archives/777.html

操作步骤如下:

  • 选型时,在同等功能时,尽量选择代码量少、占用空间小的开源的软件。
  • 控制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")

# 使用LTO
set(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")

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux2k10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值