合并Carthage dynamic framework

虽然本文中的dynamic framework是用Carthage集成的,但通样适用于任何static或者dynamic的framework。

这里有几篇文章对App launchTime造成的影响以及测量方法,可以为你提供参考:


Carthage项目中也有关于如何合并dynamic framework的文章,本文按照文章中的描述在自己项目中进行了实践,操作步骤可供大家参考。


Carthage目录概览

首先Carthage集成之后的目录大概是这样:
[图片上传失败...(image-b56b26-1512116179688)]
在Build/iOS/目录下存放的是编译好的framework和dSYM文件:


carthage_build_dir.png

让我们看一看这些framework的架构是什么样的:


framework_arch.png

可以看到,这些framework都是dynamic类型的。

看到这里不知道你会不会有疑问,这些universal的framework在编译时难道要将不需要的架构也一起link到我们的App中吗?其实不是的,在我们工程的build Phases中会添加一段Script:


carthage_copy.png

这段copy-framework命令其中做的一件事就是在编译后期copy framework到我们的App时会剔除当前不需要的架构,比如当前运行的iPhone 4s模拟器,那么只会保留i386架构,iPhone 4s真机只会保留armv7架构等等。


准备

下面合并前我们需要一个shell脚本来包装carthage build命令:

static_framework.sh

#!/bin/sh -e

xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
#trap 'rm -f "$xcconfig"' INT TREM HUP EXIT

echo "LD = $PWD/ld.py" >> $xcconfig
echo "DEBUG_INFORMATION_FORMAT = dwarf" >> $xcconfig

export XCODE_XCCONFIG_FILE="$xcconfig"

cd "$PWD/../"
carthage bootstrap "$@"

另外还需要一个ld.py脚本,别忘了用chmod +x将ld.py变为可执行文件。最后将这两个脚本文件放到Carthage目录下:
[图片上传失败...(image-7074c4-1512116179688)]


生成static framework

下面用carthage-build-static.sh将我们在Cartfile中执行的thirdLibrary重新编译成static framework,比如:

./carthage-build-static.sh FLEX --platform ios

再次查看重新生成的framework:

static_framework_arch.png

如果输出中包含current ar archive说明已经成功生成了静态framework。


将多个static framework合并成一个dynamic framework

  • 新建一个新的空白工程,target选Framework,ProductName比如叫FatDynamic

    project.png

  • 将刚才生成的那些static framework添加到工程中(切记添加的是framework中的二进制文件,不是framework本身):


    link.png
  • 添加Framework中的Header Files到工程中,记得Private Header别忘了添加:
    [图片上传失败...(image-d3a52e-1512116179688)]

  • OTHER_LDFLAGS中添加-all_load

    image

工程准备就绪,开始编译生成新的framework

我们每次选择不同的模拟器或真机只能编译生成一种架构,比如模拟器4s生成i384,5s生成x84_64,真机4s生成armv7,5s生成arm64。所以我们至少要生成这四种不同架构,然后再把这四种架构再合并起来。


不同架构.png
  • 合并不同架构
lipo -create FatDynamic_* -output FatDynamic

合并后再看一下:


合并后.png

至此我们已经将四种不架构合并到一个二进制文件中,最后将FatDynamic再替换到framework中就好了。

在工程中使用合并后的framework

  • 更改copy-framework脚本

    还记得我们在工程中添加的那个carthage copy-framework的Script吗,合并后的FatDynamic.framework添加到工程中后将copy-framework那里的输入改成FatDynamic.framework就好了。
    比如我把FatDynamic.framework放到了Carthage/Build/iOS/目录下,那么copy-framework那里就改成这样:


    copy_fat_framework.png
  • 更改工程中framework头文件
    刚才那一步操作后编译工程会出一堆头文件引入错误,原因是原来比如叫<FLEX/FLEX.h>的头文件现在必须全部要改成<FatDynamic/FLEX.h>了。


    测量

至此已经全部将dynamic framework全部合并成一个了,下面是跟合并之前在launchTime,包大小和编译时间方面做一个对比。

包大小

  • 对不同架构下对合并前后framework体积大小的测量(armv7和arm64一起测量,i386和x86_64一起测量)

Debug

架构 合并前 合并后
i386和x86_64 3.3M 2.9M
armv7和arm64 10M 2.8M

Release

架构 合并前 合并后
i386和x86_64 3.3M 2.9M
armv7和arm64 10M 2.8M
  • 对Archive出的ipa大小进行测量
ipa大小
未集成carthage 11.5M
集成Carthage 12M
合并framework后 11.8M

LaunchTime

  • 先配置环境变量


    dyld_time_config.png
  • 记录log时间输出并统计(用iPhone 6Plus真机热启动测量)

Total pre-main time: 304.60 milliseconds (100.0%)
        dylib loading time:  51.27 milliseconds (16.8%)
       rebase/binding time:  62.26 milliseconds (20.4%)
           ObjC setup time:  82.10 milliseconds (26.9%)
          initializer time: 108.87 milliseconds (35.7%)
          slowest intializers :
              libSystem.dylib :   2.74 milliseconds (0.9%)
                      Intents :  12.06 milliseconds (3.9%)
                         moma : 169.28 milliseconds (55.5%)

我们这里着重关注的是dylib loading time,分

A:只用pod集成,

B:用carthage集成,

C:合并carthage中的framework

这三种情况来测量,每次测量取10次样本。

  • A
        dylib loading time:  75.44 milliseconds (7.8%)
        dylib loading time:  26.67 milliseconds (8.1%)
        dylib loading time:  75.63 milliseconds (34.2%)
        dylib loading time:  75.24 milliseconds (33.6%)
        dylib loading time:  73.29 milliseconds (32.8%)
        dylib loading time:  25.10 milliseconds (15.3%)
        dylib loading time:  72.00 milliseconds (34.8%)
        dylib loading time:  72.42 milliseconds (26.3%)
        dylib loading time:  41.42 milliseconds (22.4%)
        dylib loading time:  74.18 milliseconds (35.4%)
  • B
        dylib loading time: 957.53 milliseconds (84.0%)
        dylib loading time: 934.26 milliseconds (84.8%)
        dylib loading time: 895.84 milliseconds (84.2%)
        dylib loading time: 891.37 milliseconds (85.0%)
        dylib loading time: 885.75 milliseconds (84.6%)
        dylib loading time: 959.70 milliseconds (86.0%)
        dylib loading time: 848.98 milliseconds (85.9%)
        dylib loading time: 891.43 milliseconds (85.3%)
        dylib loading time: 841.54 milliseconds (84.4%)
        dylib loading time: 887.29 milliseconds (84.6%)
  • C
        dylib loading time: 263.26 milliseconds (32.5%)
        dylib loading time: 210.42 milliseconds (29.4%)
        dylib loading time: 284.74 milliseconds (41.3%)
        dylib loading time: 320.13 milliseconds (66.2%)
        dylib loading time: 253.91 milliseconds (61.3%)
        dylib loading time: 267.09 milliseconds (65.5%)
        dylib loading time: 301.85 milliseconds (68.9%)
        dylib loading time: 195.40 milliseconds (58.3%)
        dylib loading time: 276.08 milliseconds (62.4%)
        dylib loading time: 194.99 milliseconds (57.0%)
  • 统计结果 (单位ms)
dylib loading time
A 61.139
B 899.369
C 256.787
  • Total pre-main time (单位ms)
A B C
1 244.00 1200 359.36
2 325.43 1300 385.02
3 242.41 1100 366.95
4 166.98 1200 365.37
5 221.46 1000 402.15
6 379.17 1000 499.69
7 582.32 1300 347.24
8 176.29 1100 328.59
9 227.55 979.21 420.61
10 161.24 1000 414.59
平均值 272.658 1117.921 388.957

编译时间测量(Release)

按上面A B C三种情况分类(单位:秒)

A B C
1 268.849 287.625 259.176
2 281.005 298.295 277.035
3 318.630 268.916 275.197
4 297.886 266.290 280.478
5 311.531 297.556 276.178
6 262.457 256.155 282.912
7 263.327 248.027 250.735
8 268.094 241.416 253.723
9 267.711 243.059 282.751
10 267.252 238.338 267.464
平均值 280.674 264.568 270.565
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,657评论 18 139
  • (原文:How to Create a Framework for iOS 作者:Sam Davies 译者:Mr...
    王宪岭阅读 4,941评论 3 23
  • 静态库与动态库的区别 首先来看什么是库,库(Library)说白了就是一段编译好的二进制代码,加上头文件就可以供别...
    吃瓜群众呀阅读 11,939评论 3 42
  • 原文链接在上一篇教程(中译版)中,你学到了怎么样创建一个可复用的圆形旋钮控件。然而你可能不清楚怎样让其他开发者更方...
    _冷忆阅读 2,448评论 9 5
  • Carthage v0.26.2(原文链接) Carthage的目标是用最简单的方式来管理Cocoa第三方框架。 ...
    iOSLee阅读 3,590评论 0 7