查找iOS上每个外部库所贡献的大小

我试图减less我的应用程序商店二进制大小,我们有很多外部库可能是最后的IPA的大小作出贡献。 有没有什么办法来找出每个外部静态库在最终的二进制文件中占多less(除了去除每个静态库?)?

所有这些信息都包含在链接地图中,如果您有足够的耐心来筛选它(对于大型应用程序来说,它可能相当大)。 链接地图列出了所有库,它们的目标文件以及打包到您的应用程序中的所有符号,所有符号均以可读的文本forms显示。 通常情况下,项目没有configuration为默认生成它们,所以您必须快速更改项目文件。

从Xcode内部:

  1. 在您的目标的“构build设置”下,search“地图”
  2. 在下面的结果中,在“链接”部分下,将“写入链接地图文件”设置为“是”
  3. 确保记下“链接地图文件的path”下列出的完整path和文件名称

下一次构build应用程序时,您将获得转储到该文件path的链接映射。 请注意,该path是相对于您在DerivedData文件夹中的应用程序的位置(通常是~/Library/Developer/Xcode/DerivedData/<your-app-name>-<random-string-of-letters-and-numbers>/Build/Intermediates/... ,但YMMV)。 既然它只是一个文本文件,你可以用任何文本编辑器来阅读它。

链接地图的内容分为3个部分,其中2个与您要查找的内容相关:

  1. 目标文件:这个部分包含你最终应用程序中包含的所有目标文件的列表,包括你自己的代码以及你所包含的任何第三方库的目录文件。 重要的是,每个目标文件也列出它来自哪里的库;
  2. 部分:本部分与您的问题无关,包含处理器部分及其部分的列表;
  3. 符号:这一部分包含您感兴趣的原始数据:所有符号/方法的列表,包括它们的绝对位置(即处理器内存映射中的地址),大小,最重要的是它们的交叉引用包含对象模块(在“文件”列下)。

从这些原始数据中,您可以获得所需的一切,以便进行所需的大小计算。 从#1中,您会看到,对于每个库,都有N个可能的组成对象模块; 从#2中可以看出,对于每个对象模块,都有M个可能的符号,每个符号都占用大小S.对于任何给定的库,那么您的大小的粗略顺序就是O(N * M * S)。 这只是给你一个进入你的实际计算的组件的迹象,这不是一个有用的公式。 为了执行计算本身,我很遗憾地说,我不知道任何现有的工具,将为您做必要的处理,但鉴于链接地图只是一个文本文件,有一点脚本的魔力和智慧你可以构build一个脚本来完成繁重的工作。

例如,我有一个小样本项目链接到以下库: https : //github.com/ColinEberhardt/LinqToObjectiveC (示例项目本身是从一个很好的教程ReactiveCocoa,在这里: http://www.raywenderlich。 com / 62699 / reactivecocoa-tutorial-pt1 ),我想知道它占用了多less空间。 我已经生成了一个链接图,TwitterInstant-LinkMap-normal-x86_64.txt(它在模拟器中运行)。 为了find库中包含的所有对象模块,我这样做:

 $ grep -i "libLinqToObjectiveC.a" TwitterInstant-LinkMap-normal-x86_64.txt 

这给了我这个:

 [ 8] /Users/Smyrl/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(LinqToObjectiveC-dummy.o) [ 9] /Users/Smyrl/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(NSArray+LinqExtensions.o) [ 10] /Users/Smyrl/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(NSDictionary+LinqExtensions.o) 

第一列包含我需要的符号表的交叉引用,所以我可以search那些:

 $ cat TwitterInstant-LinkMap-normal-x86_64.txt | grep -e "\[ 8\]" 

这给了我:

 0x100087161 0x0000001B [ 8] literal string: PodsDummy_LinqToObjectiveC 0x1000920B8 0x00000008 [ 8] anon 0x100093658 0x00000048 [ 8] l_OBJC_METACLASS_RO_$_PodsDummy_LinqToObjectiveC 0x1000936A0 0x00000048 [ 8] l_OBJC_CLASS_RO_$_PodsDummy_LinqToObjectiveC 0x10009F0A8 0x00000028 [ 8] _OBJC_METACLASS_$_PodsDummy_LinqToObjectiveC 0x10009F0D0 0x00000028 [ 8] _OBJC_CLASS_$_PodsDummy_LinqToObjectiveC 

第二列包含符号的大小(hex),所以如果我把它们全部加起来,我得到0x103或259字节。

更妙的是,我可以做一些简单的黑客攻击来减less基本要素,为我做些补充:

 $ cat TwitterInstant-LinkMap-normal-x86_64.txt | grep -e "\[ 8\]" | grep -e "0x" | awk '{print $2}' | xargs printf "%d\n" | paste -sd+ - | bc 

这给我直线的数字:

 259 

"\[ 9\]" (13016字节)和"\[ 10\]" (5503字节)进行相同的操作,并将它们添加到前面的259个字节中,得到18778个字节。

你当然可以改进我在这里完成的黑客入侵,以使其更强大(在这个实现中,你必须确保你得到的空格的确切数量正确,并引用括号),但你至less得到理念。

制作应用的.ipa文件并将其保存在系统中。

然后打开terminal并执行以下命令:

unzip -lv /path/to/your/app.ipa

它将返回一个关于你的.ipa文件的数据表。 大小列具有您的.ipa文件中每个文件的压缩大小。

在xcode中构build应用程序。

然后使用发现者来探索内容,这应该给你足够的信息,包括什么。

我认为你应该能够从中提取你需要的信息:

符号-w -noSources YourFileHere

参考: https : //devforums.apple.com/message/926442#926442

IIRC,它不会给你清楚的每个库的摘要信息,但你应该发现,每个库的function应该聚集在一起,所以你可以通过一些努力来计算每个库的大致贡献:

还要确保在生成设置中将生成debugging符号设置为NO。 这可以减less约30%的静态库的大小。

万一它是你的关注的一部分,一个静态库只是相关的.o文件一起归档加上一些簿记。 所以1.7mb的静态库 – 即使其中的代码是整个1.7mb – 通常不会增加1.7mb到您的产品。 有关死代码剥离的通常规则将适用。

除此之外,您可以减less代码的内置大小。 以下可能不是一个全面的列表。

在目标的构build设置中查找“优化级别”。 通过将其切换为“最快,最小的-Os”,您将允许编译器牺牲一些速度。

确保你正在构build更紧凑的ARM代码。 假设您使用LLVM,这意味着确保在项目设置中的任何位置都没有-mno-thumb。

还要考虑要为其构build的体系结构。 苹果不允许提交支持ARMv6和iPhone 5屏幕的应用程序,并完全从最新的Xcode中删除ARMv6支持。 所以在这一点上可能没有任何意义。

有一个非常简单的应用程序称为OmniDiskSweeper,它基本上是在您的硬盘驱动器find大量的文件,但只是导航到您的构build和检查里面的文件。 但我不认为图书馆是负责任的,也可能有一些大的图片。 我总是使用名为ImageOptim的工具https://imageoptim.com/来压缩我的项目中的所有图像,这是非常有用的,因为图像压缩高达99%,具有相同的质量&#x3002; 要使用该工具,只需下载并安装它,然后从terminal(在您的项目文件夹中)input:

 open -a ImageOptim .