天超,携程资深软件工程师,关注iOS研发,喜欢用脚本语言解决各种难题。
引言
开发效率的提升,是开发者关注的一个永恒的话题。对于iOS而言,编译速度一直是影响iOS开发和集成测试效率关键的一环。
携程旅行App iOS工程编译,经历了从全源码编译到工程组件化,细分Bundle,再到细分Bundle基础上的进一步优化四个阶段。每次的优化改造都是不断结合业务反馈,深入了解xcode编译过程后的成果。
一、背景
简单回顾一下在做Bundle拆分之前的情况,当时整个iOS工程的所有代码都在一起,并未做工程拆分和解耦,编译时全都是源码编译,数百万行代码全部编译完成要将近一个小时。所有的开发人员都在一个工程里开发,如果因为某个人提交的代码有问题(这是常常会发生的),导致编译了很长时间之后才 错,更是耽误时间,严重影响开发效率。对于测试人员来说,每次需要验证一个功能时打包测试都需要至少等待几十分钟,这是极大的资源浪费。
这个时候的Build过程是全源码complie,几千上万个文件都需要编译、链接,效率可想而知。
App Build:
2)使用Jenkins插件建立Bundle和节点的关联
基于Jenkins Label Parameter Plugin,并做改造,实现伪随机,以保证关联的节点下线之后,能使用候补节点正常工作。
发布平台前端提供关联配置,业务可以按需选择使用。
以某一个编译源码文件197个、资源文件142个的Bundle为例看下效果。
2.3 Bundle细分
最初携程旅行App的Bundle都是按照业务来拆分的,比如:酒店就一个Hotel Bundle,在当时编译速度已经不慢了。但是随着业务的发展,单个Bundle中业务代码越来越多,文件越来越多,导致编译又会变慢。这时,可以将单个Bundle按照功能做更细粒度的拆分,比如酒店拆分出了酒店主工程、酒店基础工程。
更细粒度的Bundle拆分还能带来以下其他收益:
-
加快本地开发编译:某个功能的开发人员只需要将自己这个功能模块切为源码,其他模块全用静态库,提高本地开发编译效率。
-
为其他独立app提供更细粒度的模块功能支持:我厂的很多独立App都是共用一套框架和基础组件的,按功能模块细粒度的拆分出独立的模块Bundle后,可以使独立app在选择基础组件时按需选择。
2.4 合理设置头文件搜索路径
业务工程往往会大量依赖基础库代码,在本工程编译过程中,也需要查找到引用的基础代码的头文件。
因为代码还是在同一个仓库里,之前的方案是头文件搜索设置还是指向本地的基础框架代码,使用循环搜索的方式。
这样的好处是任何一个头文件的修改,使用方可以马上感知到。
缺点就是头文件没有特意为方便调用进行组织,搜索起来特别费时。
经过统计,Hotel一个文件的编译往往都是秒级别。一整个工程编译下来就是十几分钟。
因此框架团队意识到必须要和第三方库一样,在目前的.a和资源文件之外,提交include目录包含所有会被外部使用的头文件。
同时,考虑到iOS开发向Swift转型的需要,如果在include目录的基础上,还能够提供一份基于include里头文件的module.mapmodule文件。将方便后期业务方向Swift的迁移。
具体方法是:
1)首先框架的Bundle,在工程设置中点击工程的Target→Build Phases→Copy Files点击+,输入.h把需要暴露的头文件都添加上。
这样会在输出产物的Build目录下,多一个include目录,再通过脚本去把这个目录里面的所有文件复制出来,同时生成module.mapmodule。
2)使用的时候,将头文件搜索路径设置到include目录,并且设置为非递归搜索。
所有Bundle全量更新一次耗时:
《携程架构实践》
当当
京东
分享,交流,成长
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92925 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!