我们的iOS SDK采用静态库形式分发,不知不觉SDK已经增大到几百M,而实际安装包增量不过几M,有必要反思一下为何SDK体积如此之大。
什么是静态库
静态库简单的理解是多个目标文件(.o)的打包集合。静态库在unix系统上后缀一般是.a,苹果上既可以用.a,也可以封装成Framework形式。
静态库的好处是提供的是目标文件,所以不需要重新编译,只需要链接即可,相比动态库,加载速度更快。在链接的时候,链接器会保留用到的代码,没有用到的代码最终会被删掉(Dead code),这就是为什么静态库很大,编出来的app却很小。从这点看,静态库在体积上相比动态库会有一点优势。
如何减小静态库体积
1. 关闭Debug Symbols
在"Build Settings",将"Generate Debug Symbols"设置NO。这是最快、最直接的方法,立马可以节省20%的体积。
注意:设置为NO只能去除当前工程的符号,引用的第三方还是没处理。建议将对第三方的静态库做一下strip。
2. 不重复link静态库
我们的SDK分为多个子模块,子模块相互独立,但可能使用相同第三方库。
SDK.framework ++-----> Module A (A.a) +-----> Third.a
|
+-----> Module B (B.a) +-----> Third.a
静态库的生成实质就是一个打包过程,并且打包相同文件不做去重。所以SDK中包含了两份Third.a目标文件。包依赖改为下面形式就能减少重复依赖。
SDK.framework ++-----> Module A (A.a)
|
+-----> Module B (B.a)
|
+-----> Third.a
我们SDK有一些很大的第三方静态库,通过这一步减少了上百M。
3. 去除无用目标文件
SDK很多第三方库,包括自身代码,很多文件至始至终都没有被使用,这部分文件其实可以不编译。
如何找到那些目标文件被使用?这时需要求助link map文件。在测试demo中打开link map生成,打开文件后可以看到如下:
# Arch: arm64
# Object files:
[ 0] linker synthesized
[ 1] /Users/annidy/Library/Developer/Xcode/DerivedData/TXLiteAVDemo-ctawhuyhhsutohfizsupuzlyqmki/Build/Intermediates.noindex/TXLiteAVDemo.build/Release-iphoneos/TXLiteAVDemo_Player.build/Objects-normal/arm64/TXCAudioCustomRecorder.o
[ 2] /Users/annidy/Library/Developer/Xcode/DerivedData/TXLiteAVDemo-ctawhuyhhsutohfizsupuzlyqmki/Build/Intermediates.noindex/TXLiteAVDemo.build/Release-iphoneos/TXLiteAVDemo_Player.build/Objects-normal/arm64/AFAutoPurgingImageCache.o
...
[212] /Users/annidy/Library/Developer/Xcode/DerivedData/TXLiteAVDemo-ctawhuyhhsutohfizsupuzlyqmki/Build/Products/Release-iphoneos/TXLiteAVDemo_Player.framework/TXLiteAVDemo_Player(TXCAVRoomConfig.o)
[213] /Users/annidy/Library/Developer/Xcode/DerivedData/TXLiteAVDemo-ctawhuyhhsutohfizsupuzlyqmki/Build/Products/Release-iphoneos/TXLiteAVDemo_Player.framework/TXLiteAVDemo_Player(TXUGCSign.o)
SDK和Demo用的的文件都列了出来,没在里面的文件就是不需要的目标文件。
link map文件比较大,可以通过下面脚本提取出文件名
#!/bin/sh
grep -oE '[^\/\(]+(\.o)' $1 | grep -v ' '
接下来可以在工程里进行搜索,去掉不需要的文件。
4. 关闭bitcode
bitcode在编译的时候embed到目标文件中,通常比代码段还大。如果不需要支持bitcode,去掉还是能省至少50%的大小。
xcode提供了一个bitcode_strip
工具,可以很方便的来去除。
通过以上步骤,将静态库减小到原先的1/5,可谓巨大进步。
网友评论