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

标签 ios xcode linker uikit

我正在尝试减少我的应用商店二进制文件大小,我们有很多外部库可能会影响最终 ipa 的大小。有没有办法找出每个外部静态库在最终二进制文件中占用了多少(除了要删除每个库?)?

最佳答案

所有这些信息都包含在链接 map 中,如果您有耐心筛选它(对于大型应用程序,它可能非常大)。链接映射列出了所有库、它们的目标文件以及打包到您的应用程序中的所有符号,所有这些都以人类可读的文本形式出现。通常,项目未配置为默认生成它们,因此您必须快速更改项目文件。
在 Xcode 中:

  • 在目标的“build设置”下,搜索“ map ”
  • 在下面的结果中,在“链接”部分下,将“写入链接映射文件”设置为"is"
  • 请务必记下“链接映射文件的路径”下列出的完整路径和文件名

  • 下次构建应用程序时,您将获得一个链接映射转储到该文件路径。请注意,该路径是相对于您的应用在 DerivedData 文件夹中的位置(通常是 ~/Library/Developer/Xcode/DerivedData/<your-app-name>-<random-string-of-letters-and-numbers>/Build/Intermediates/...,但 YMMV)。由于它只是一个文本文件,因此您可以使用任何文本编辑器来阅读它。
    链接 map 的内容分为 3 个部分,其中 2 个部分与您要查找的内容相关:
  • 对象文件:本部分包含最终应用程序中包含的所有对象文件的列表,包括您自己的代码和您包含的任何第三方库的代码。重要的是,每个目标文件还列出了它来自的库;
  • 部分:此部分与您的问题无关,包含处理器段及其部分的列表;
  • 符号:本节包含您感兴趣的原始数据:所有符号/方法的列表及其绝对位置(即处理器内存映射中的地址)、大小,最重要的是,对它们的交叉引用包含对象模块(在"file"列下)。

  • 从这些原始数据中,您可以获得进行所需尺寸计算所需的一切。从#1,您可以看到,对于每个库,有 N 个可能的组成对象模块;从 #2 中,您可以看到,对于每个对象模块,有 M 个可能的符号,每个符号占用大小 S。对于任何给定的库,您的粗略大小顺序将类似于 O(N * M * S)。这只是为了让您了解实际计算中的组件,它不是任何有用的公式。要执行计算本身,我很抱歉地说我不知道​​任何现有的工具可以为您进行必要的处理,但鉴于链接图只是一个文本文件,具有一点脚本魔法和独创性您可以构建一个脚本来完成繁重的工作。
    例如,我有一个链接到以下库的小示例项目:https://github.com/ColinEberhardt/LinqToObjectiveC (示例项目本身来自 ReactiveCocoa 的一个很好的教程,此处:http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1),我想知道它占用了多少空间。我生成了一个链接图,TwitterInstant-LinkMap-normal-x86_64.txt(它在模拟器中运行)。为了找到库中包含的所有对象模块,我这样做:
    $ grep -i "libLinqToObjectiveC.a" TwitterInstant-LinkMap-normal-x86_64.txt
    
    这给了我这个:
    [  8] /Users/XXX/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(LinqToObjectiveC-dummy.o)
    [  9] /Users/XXX/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(NSArray+LinqExtensions.o)
    [ 10] /Users/XXX/Library/Developer/Xcode/DerivedData/TwitterInstant-ecppmzhbawtxkwctokwryodvgkur/Build/Products/Debug-iphonesimulator/libLinqToObjectiveC.a(NSDictionary+LinqExtensions.o)
    
    第一列包含对我需要的符号表的交叉引用,因此我可以搜索这些:
    $ 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
    
    第二列包含有问题的符号的大小(十六进制),所以如果我把它们全部加起来,我得到 0x103 或 259 字节。
    更好的是,我可以做一些流黑客攻击,将其缩减为基本元素并为我做补充:
    $ 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 个字节。
    您当然可以改进我在这里所做的流黑客攻击,使其更加健壮(在此实现中,您必须确保获得正确的空格数并引用括号),但您至少得到主意。

    关于ios - 查找 iOS 上每个外部库贡献的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32003262/

    相关文章:

    ios - 屏幕关闭时,Watch OS3无法获取加速度计数据

    ios - 在 UITableViewCell 中重复一个 UILabel

    ios - 公式键盘 ios

    c++ - 丢弃理论上使用但技术上未使用的功能

    c - nm 命令输出中的奇怪符号名称

    ios - 替换两个字符串之间的字符串

    objective-c - 使用 UIButtons 和 CoreAnimation 创建柔和的随机运动

    swift - 将 ASValueTrackingSlider 连接到我的代码时出现未知错误

    c - Lua liblua5.1.so 无法打开共享对象文件

    ios - TabViewController 中未调用 prepareForSegue