百度App iOS工程化实践: EasyBox破冰之旅

原创:Yunpeng-基础技术 百度APP技术团队

前言

百度App从单一的搜索工具发展到今天以搜索和Feed流为双引擎的综合性内容消费服务平台,其复杂程度已然不可同日而语矣。 作为一个日活过亿的超级App,业务规模庞大,相关技术人员超过千人,客户端支持主流的移动技术,涉及近百业务方,技术形态复杂,各种组件近三百个,代码百万量级,由此带来的工程化问题是技术团队的一个极大挑战。

项目的膨胀导致了很多不起眼的小问题被无限放大,组件管理不规范、编译时间长、工程文件合并冲突、Xcode默认非彻底编译隔离等等问题,导致开发人员在开发环境上耗费了大量时间。目前业界较流行的工具对于大规模工程的支持力度相对较弱,实践起来总是有些掣肘,难以达到理想状态。

EasyBox的诞生,就是致力于为超级App量身打造一套现代、高效、优雅的研发工具链。

这篇文章的主要目的是站在工具链的角度上,分享一下我们在实践工程化过程中一些经验。

概述

EasyBox主体由工程组装器(Installer)、多仓库管理工具(MGit)、二进制管理工具(LFS)三部分构成,分别负责工作区的构建(组件依赖分析、工程的生成与组合)、源码仓库的管理以及二进制的管理。

EasyBox架构图

由多仓库管理工具克隆所需仓库源码,由二进制管理工具下载二进制包,然后组装器根据描述表生成对应工程,组合层级并最终生成Workspace。

简化工作流程示意图

实践

EasyBox诞生的过程本质上是工程化逐步深入的过程。分而治之的道理大家都明白,但这并不意味着工程化就是简单的拆库重组。其目的是要对项目工程进行合理化改造,让开发人员能够快速理解工程架构并进入开发状态,避免开发人员在开发环境上花费过多时间,从而提高编码、测试等阶段的研发效率。在这个过程中我们在规范组件管理与使用、强化工程能力、提升编译速度这三个方面不断优化,最终形成EasyBox独特的优势。

1.规范组件管理与使用

组件(源码/二进制)统一使用描述表(boxspec)描述,依赖与API管理均由描述表唯一决定,配合编译隔离使得组件边界划分明确。组件的版本号严格遵守语义化版本(Semantic Versioning)规范,组件新版本发布时,需经过持续集成分析API变化等一系列检查之后方可完成发布。

破窗理论 环境中的不良现象如果被放任存在,会诱使人们仿效,甚至变本加厉。

组件基于源码发布来完成二进制发布及接口发布,以确保安全性,方便进行源码回归校验以及必要时基于同一节点发布不同类型的二进制,接口发布用于完成矩阵产品的组件替换。发布版本的描述表与二进制文件交由专门的文件服务器管理,并禁止二进制文件入源码仓库以避免仓库膨胀。更多源码与二进制管理细节参见后文介绍。

2.强化工程能力

2.1组件的独立与隔离

与业界其他大多数工具不同,EasyBox采取了每个组件都拆分为独立工程的方案,同时也将不同的组件的编译产物放在了不同的目录下,这样做的目的是确保彻底的编译隔离

这里其实是源自Xcode的遗留的两个坑:

  • 同一个工程的OC/C/C++文件就算不在同一个Target下且没有依赖关系也可以互相访问(Swift是不允许的)。

  • Xcode会自动将编译产物所在的文件夹(BUILD_PRODUCTS_DIR)添加到 FRAMEWORK_SEARCH_PATHS 中,而同一个Workspace下的编译产物默认是在同一文件夹下的。

这两个坑都会打破编译隔离,后者更会导致在不同开发者的电脑上编译结果不同,时常出现自己编译过了而别人编译不过的情况,这是其实由于组件编译次序不同导致的。

但由于Xcode工程文件一直是饱受诟病的设计,多人协作时工程文件合并冲突简直就是一场噩梦,所以我们采用了组件配置表的方案来完成去工程文件化,每个组件通过配置一个boxspec文件(类似于CocoaPods的podspec),组件源码会根据实际目录映射对应工程结构,同时生成一个xcfilelist来维护当前组件所配置的资源列表,并最终生成工程文件。该工程文件不被Git追踪,从而避免合并冲突问题。

编译隔离可以带来很多好处,比如组件边界一定是明确的,几百个组件组合在一起能不能编译过不再看"运气"。它限制了组件修改时所影响的范围,这将有助于组件在不同环境(App)下编译构建、多端复用,使得输出时开发者对于组件的依赖是有预期的。

另外配合接口发布及组件化中的协议解耦,使得组件输出时可以选择性的只携带其他组件的接口(而非实现),从而很容易地完成依赖组件的剥离与替换。

boxspec描述表示例

自动生成组件工程示例

2.2多仓库的拆分与管理

代码集中管理导致主仓库越来越臃肿,而且代码权限问题难以管理,这对于大团队的开发而言是个非常痛苦的事情,很容易出现组件在负责人不知道的情况被其他人合入代码,加之一定的组件易手率,情况会变得更加糟糕。

熵增原理 在自然情况下,一切物质都将趋向于无序

为解决这个问题,我们将各组件拆分为独立仓库,完成物理隔离,做到入库权限收紧,物各有主。另外这对于多产品复用起了至关重要的作用,也是中台化建设的必要条件。在实际实践过程中,为了避免某些仓库过于琐碎,也会出现一个仓库多个组件的情况,但并不影响大局。

多仓库的拆分从某种程度上加剧了工程的复杂度,开发者不可避免地出现需要操作多个仓库的情况,这时直接使用Git操作成本高且易出错,为此我们专门设计了多仓库管理工具(MGit, Android/iOS双端共用)。与Android系统源码多仓库管理工具Repo不同,MGit保持了Git的大多数指令和用法,同时在内部执行时保证多仓库操作的安全性,在执行风险操作时做出必要提醒。开发者只需使用 mgit 替代 git 命令即可完成多仓库操作,这样既保持了大多数开发者的使用习惯,又可以安全方便地同时操作多个仓库。同时我们利用Gerrit的topic机制并加以改造,实现多仓库的分组提交以确保原子性入库,进而保证自动打包机制的正常运作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值