抛弃Xcode依赖管理,单仓多组件下编译加速(小作坊向)

前言

本方案适合于单仓库(Monorepo)方式管理的项目,通过二进制化的想法减少编译工作量,并通过抛弃Xcode的自带的依赖管理机制,建立自定义的依赖管理去实现开发时的编译加速。本方案可做到对原项目无侵入性,兼容两套依赖管理机制,既可用Xcode进行依赖管理,也可以使用自定义的方式进行依赖管理,任何项目均可放心使用。
(本方案基于项目已经组件化,未组件化项目可先进行组件化再实施,整体改造难点在于依赖管理改造)
项目改进后,会有飞一半的质感,让大项目的编译速度回归到小项目一样。


image.png

如图,修改了组件A、组件C情况下,原Xcode依赖管理方案进行管理时,执行build clean后会重新编译所有代码编译。依赖管理改进方案只需要执行编译主工程、组件A、组件C,即完成编译工作,大大缩短了编译时间。

对Xcode熟悉以及对自身项目熟悉的开发者两天内可以完成改造,最长不超过一周时间,可以说成本很低,而且不影响原有项目的构建方式。

思路与原理

  1. 二进制组件化与多仓库管理陷阱
    通过对组件预先编译得到二进制文件,那么在开发时主工程只需要执行链接的过程就可以完成构建工作。


    图1
图2

如图2所示,通过将主工程拆分为组件后,通过对组件预先编译得到二进制文件,主工程构建时只需要对组件进行链接则可完成构建,时间可以大大缩短。理论上,主工程拆分出来越多,构建时编译时间就会越少。
通过以上的思路,很容易就会走向多仓库项目管理,Cocoapods一上,项目管理得整整齐齐。
但是,项目的组件依赖往往不如图2那么简单。如图3,组件D依赖组件A和B,修改组件A需要重新编译和发布组件A和组件D。(现实状况会比图3复杂的多得多)


图3

虽然通过二进制化组件可以减少编译时间,但是一旦使用多仓管理这种重型项目管理方式,会使团队陷入了无止境的编译发布流程,光是Debug的工作就是噩梦般的存在。小项目,小团队使用多仓管理,等于把自己推向深渊。

  1. 单仓多组件全量编译工作量过大
    单仓多组件没有组件发布流程,debug时也像无组件工程一样来去自如。这种组件化方式却无法缩短编译时间,只得到了分层的好处。
    当然,还可以做成单多仓结合,业务组件修改频繁,放在主仓库,底层稳定组件封装,放在分仓库。这种方式能解决部分问题,但是编译时间还是冗长,毕竟业务组件基本都是大头。
    如图4,当组件A修改后,理论上只需要重新编译A、D和主工程,但是实际操作上,一个Clean动作就把组件B、C的编译产物也清理了。也就是说,在单仓情况下,全量编译的情况是非常普遍的。


    图4
  2. 单仓多组件二进制化
    所以,是否存在一种方案,在单仓多组件的项目管理方式下,解决如图4出现的,对组件B和组件C的冗余编译工作?
    毫无疑问,理论上,这肯定是存在,因为构建的工作就是这样执行的。图4的情况下,保留组件B和组件C的编译产物就可以做到。
    因此,我们需要对工程进行改进,把编译产物二进制文件缓存下来,并使用它们。(其实整体思路有点像增量编译那套,只是缓存的颗粒大一些)

如图5,通过对二进制产物缓存起来,并在项目中链接使用该产物,则可以实现。虽然看似简单,但实际上是需要将原来交由Xcode托管的依赖管理机制重新实现一遍。


图5

4.依赖计算以及编译顺序
如图5中,修改了组件A,需要计算出需要重新编译的组件和顺序是:A、D。因此,若实施方案,则需要先梳理好所有组件的依赖关系,而不是像原来一样交个Xcode计算。确定好需要重新编译的组件后,安装依赖关系对组件按顺序重新编译。

5.增量编译兼容
实际工作中,需要执行增量编译。比如,上一次编译中,修改了组件A、D,也编译了组件A、D,后续又修改了D,则本次只需执行编译组件D,而不是组件A、D。而且,组件D执行的是增量编译,秒级的,而不是全量编译。笔者的方案是通过git diff进行hash计算修改,并使用Xcode的自身的增量编译。

实践

·基础知识
  1. Xcode的依赖管理
    Xcode的依赖管理分为两种,第一种是显式依赖(Dependencies),第二种是隐式依赖(Implicit Dependencies)。
  • 显式依赖(Dependencies)的管理放在了Build Phases下的Dependecis栏,开发者可以手动添加依赖,仅限workspace下的target
  • 隐式依赖(Implicit Dependencies)是XCode在构建时进行计算得出的,具体计算范围是显式依赖基础上,叠加project下被链接的库(Link Binary With Libraries 以及 手动链接的库)
  1. Scheme、Target
    Scheme是管理各种构建等配置的地方,其中有一项是隐式依赖的开关
    Target是管理构建信息的地方,普通项目的target对应一个构建产物
    Scheme和Target的概念大家可以网上找找,此处不赘叙。
·具体方案

整体构建流程:


image.png

Step0. Scheme处理
·为了不影响原构建方案,需要额外新建一个主工程的scheme,直接Xcode上new scheme,选择主工程(todo: 配图 打码)
·修改所有project的scheme,取消所有工程的Find Implicit Dependencies,从而取消Xcode的隐式依赖管理。

Step1. Target处理
·新建一个target,直接对原主工程target duplicate一个,并完善info.plist的指向


image.png

·新建一个target,选择脚本(本方案通过脚本执行组件的依赖管理以及构建工作)


image.png

·修改目标工程的依赖,新增脚本依赖


image.png

Step2. 缓存构建产物
·项目中新建文件夹对产物进行缓存,修改.gitignore
·主项目和子项目framework的链接地址(Link binary with Libraries)全部指向缓存文件夹

·通过脚本完成编译的组件二进制产物放到缓存文件夹(切记使用cp命令,不要使用mv命令,否则Xcode增量编译失效)

Step3. 依赖关系梳理(脚本实现)

Step4. 计算出需要编译的组件(脚本实现)
· 缓存文件夹中无的组件需要编译
· 被修改的组件需要编译
· 组件中依赖的组件被编译的需要重新编译

Step5. 执行构建(脚本实现)

Step6. git diff 文件hash计算
每个git diff的hash值对应一个二进制文件产物,通过hash值的比对来确定修改是否已经编译过。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容