知乎 iOS 客户端工程化工具 Venom

2019 年 6 月 25 日

知乎 iOS 客户端工程化工具 Venom

前言


知乎 iOS 客户端从一开始围绕问答社区到目前涵盖 Feed,会员,商业,文章,想法等多个业务线的综合内容生产与消费平台。项目的复杂程度已经在超级 App 的范畴。单周发布与业务并行开发也逐渐变成主流。同时在知乎 iOS 平台,技术选型一直也都比较开(sui)放(yi)。较早了引入了 Swift 进行业务开发,列表引入了需要 OC++ 的 ComponentKit 作为核心引擎。所以在这种多业务方团队,技术形态复杂,组件仓库数量多等场景下,也同样遇到了各种超级 App 团队都面临的一些问题。


问题如下:


  • 如何统一开发环境

  • 提高编译速度

  • 提高打包速度

  • 二进制组件调试

  • 多组件联合调试

  • 多组件联合打包

  • 约束组件依赖关系等


当然在思考解决上面这些问题前,知乎 iOS 项目也同样经历过组件化的工作。与众多组件化拆分方案殊途同归,进行了业务划分,主仓库代码清空,业务线及 SDK 进行独立仓库管理。引入基于路由,基于协议声明的组件间通信等机制等,这里就不多赘述了。


简介


核心介绍的项目名称为 Venom,灵感来源于电影《毒液》。Venom 的用户端是一款为开发人员打造 Mac App,应用内置了工程构建需要的全套 Ruby Gem 和 Cocoapods 等其相关构建环境。核心目标是解决工程构建,二进制构建,组件管理,调试工具等一系列开发过程中的繁琐耗时任务。



所以当一台全新的 Mac 电脑希望运行工程时, 只需要 3 步:


  1. 安装 Venom For Mac 客户端。

  2. 使用 Venom 打开工程点击 Make 按钮。

  3. 构建完成点击 XCode 按钮打开工程。(当然默认己装 XCode )


从此告别 ruby,cocoapods 版本不对,gem 问题,bundle 问题以及权限问题等困扰。因为构建环境内置,使得构建环境与工程师本地环境隔离,极大的降低了工程 setup 的成本。


完整的 Venom 包含了 3 个部分:


  1. Venom App

  2. Venom 内核

  3. Venom Server



下面会着重介绍客户端和内核相关的技术方案,数据服务目前仅为组件的附加信息提供 API 支持。


Venom 内核介绍


在引入 Venom 前,一直使用 Cocoapods 的 Podfile 进行组件的引用。但如果希望对 pod 命令的 DSL 进行扩展,发现是不够方便的。索性在 Cocoapods 上层建立自己的组件描述文件,每一个描述文件最终都会被转化为一次 podfile 的 pod 调用。



如上图,使用 Venom 方式集成的项目,由在 VenomFiles 目录内的组建描述文件组成。


组件描述文件


VenomFile.new do |v|
v.name = 'XXModuleA'
v.git = 'git@git.abc.abc.com:Team-iOS-Module/XXModule.git'
v.tag = '1.0.0'
v.binary = false
v.use_module_map = true
v.XX...
end

复制代码


组件描述文件可以理解是 pod 命令的一个超集,在包含了 pod 的原有功能基础上,扩展其他功能(胶水代码创建,二进制化与源码切换等)。


组件调试


同时在与 VenomFile 同级别还设计了一个 Customization.yml 的文件。当开发过程中,需要对某个组件进行源码二进制的切换,或者源码路径的切换,版本引用的切换等,不会直接改动 VenomFile,会改动 Customization.yml 来进行。在构建过程中的优先,Customization.yml > Venomfile 。为了每个工程师的改动不会互相影响,Customization.yml 是非 git 托管的。而 VenomFiles 内的文件只有更新版本号或其他配置改动,才会更新。


构建过程


所有组件都通过一个个 Venomfile 文件方式管理在主工程仓库中,通过目录对组件进行层级划分管理。



原来的 Podfile 文件通过嵌入 Venom 进行构建职责的接管。



使用 Venom 后 pod install 的实际过程就如下图:



整体上来看, Venom 内核提供了一套扩展 pod 属性的描述文件,开发阶段通过 customization.yml 进行可配置的构建。构建过程中,依赖 Venomfile 文件的唯一标识进行二进制库和源码的关联。通过对 Cocoapods 构建过程的 hook 实现二进制与源码的引用切换。二进制化方案可参考 :


Xinyu Zhao:知乎 iOS 基于 CocoaPods 实现的二进制化方案​


命令接口


Venom 内核除了主要的构建职责,还提供了一系列的 ipc 命令。通过这些 ipc 命令,上层的 Venom 客户端就可以更容易的操作每个组件,进行定制化的开发组织。来构建工程。


例如:


// 修改组件二进制使用方式,使用二进制
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--binary
// 修改组件二进制使用方式,使用源码
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--source
// 修改 yml 文件中指定组件的路径
venom ipc customization \
--path /Users/abc/Developer/zhihu/abc/def \
--edit \
--name ZHModuleABC \
--pod_path /path/to/ZHModuleABC
// reset 某个组件在 customization 中的 change,不指定 name 参数会给整个文件置成空
venom ipc customization \
--path /xxx \
--reset \
--name ZHModuleABC

复制代码


Venom App 介绍


通过对 Venom 内核的简单介绍,其实可以认为,只通过命令行版的工具,就可以达到用到的大部分功能。但因为实际开发情况一般不会一个人一次只处理一个模块,所以希望以一种所见即所得方式来让业务工程师不用关心下层的逻辑,学习命令。可以快速建立起开发环境是我们的主要目标。



客户端主要模块


Venom App 内置了全套的 guby gem 环境来运行命令。通过 CLITask 来访问 Venom-core 以及 git 等其他命令(venom 内核一样内置在 Venom App 内)。



这样很好的控制了执行命令的环境,特别是对新入职的员工是十分友好的。


核心功能


开发组件关联


正常情况下 clone 下来的主工程(壳工程)内是没有代码的,只有空的工程文件和组件描述文件。Venom 工具划分了 2 个区域,普通组件和定制组件。



因为每个开发者维护的组件其实是有限的几个,一般都会将源码放在固定目录,所以通过设置客户端的自动扫描路径。在 Venom 界面上,如果在扫码路径下发现了相关组件,则可以一键关联本地目录组件,这样组件会切换到定制组件的模式进行开发。


特定版本关联



在开发过程中,有时需要对某一个依赖库的特定版本进行调试或连调。所以也支持通过 tag,commit,branch 等方式,进行特定源码的切换和关联。


源码与二进制切换



某些特殊场景下,可能希望工程以所有组件都是源代码方式构建,排查问题。那么也可以通过 2 种不同的构建模式一键切换。(当然全源码构建一次需要十足的耐心)


二进制模式下搜索与调试


二进制化后,大部分情况下都工作在二进制模式下,但有时在进行源码搜索时,希望可以全局搜索。所以在构建过程中,会把当前版本的源码目录也引用到工程目录下。



所以在工程进行检索代码时,是完全没问题的。有了源码,在云端进行二进制打包时,通过 fdebug-prefix-map ( Clang command line argument reference )这个参数重新在二进制文件中改写 Debug 模式的源代码路径。这样即使在二进制模式下,也可以直接关联源码进行断点调试。


组件依赖关系分析


当组件很多后,就会出现一些工程师对组件所处层级不够了解,导致出现依赖混乱的问题。所以在构建结束后会通过对组件层级的检查,进行组件依赖层级的判断。



总结


在推进所有工程师使用 Venom 客户端后,相当于在开发环节有了一个强有力的抓手。由于 App 的自动更新功能,可以在平台下提供给开发者更多的工具,而开发者只需要更新客户端使用。通过工具化客户端的开发,我们重构了原有散落在各处的脚步,工具集中整合在一起。使得开发工具维护更统一,更新也更及时,开发人员上手成本也更低。


Venom 核心承担的是开发环境管理,工程组织与构建管理,提高工程效率工作。但上线后,我们还陆续在此基础上提供了一些其他功能。


  • 多仓库 MR 自动填充提交

  • 本地非独立业务仓库单元测试

  • 个人开发者账号真机调试

  • 无用图片扫描工具

  • 轻量的 app 网络和日志查看等


本文转载自知乎技术专栏


原文链接


https://zhuanlan.zhihu.com/p/69526642


2019 年 6 月 25 日 08:00 19023

评论

发布
暂无评论
发现更多内容

架构师训练营 1 期 -- 第二周作业

曾彪彪

架构师训练营第 1 期

依赖倒置及接口隔离原则

天天向上

架构师训练营第 1 期

依赖倒置原则

知行合一

软件设计原则

架构师训练营第 1 期 -- 第二周作业

发酵的死神

架构师训练营第 1 期

架构1期第二周作业

FG佳

架构师训练营 1 期 -- 第二周总结

曾彪彪

架构师训练营第 1 期

第二周总结

睁眼看世界

架构师训练营第一期

Spring 5 中文解析数据存储篇-JDBC数据存储(上)

青年IT男

Spring5

开源推荐:国内3大主流前端UI表单设计器,千万不要让领导知道

互联网应用架构

Vue Element antd

深拷贝与浅拷贝到底是什么

C语言与CPP编程

c++ 面试题 C语言

训练营第二周作业1

Yangjing

架构师训练营第一期

架构师训练营第 2 周学习总结

netspecial

架构师训练营第 1 期

第二周作业

alpha

架构师训练营第一期

食堂就餐卡系统设计-作业

Kenny

作业

十七张图玩转Node进程——榨干它

执鸢者

前端 进程 Node

什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?

魏小龙

敏捷开发 依赖倒置原则

架构一期 - 甘霖 - Week2 - 作业一

小粽

Mac mini 2020上手体验

墨凡

Mac

架构师训练营第二周学习感悟

听夜雨

架构师训练营第 1 期

面试中常见的C语言与C++区别的问题

C语言与CPP编程

c++ 编程语言 面试题 C语言 编译器、程序语言、CPU

荷之美 | 中国荷苑

xcbeyond

生活 摄影 摄影征文 荷花

架构师训练营学习总结——第二周

文智

架构师训练营第一期

week1--作业一

hero_genlot

架构师训练营第 1 期

一文轻松理解内存对齐

C语言与CPP编程

程序员 编程语言 面试题 C语言 编译器、程序语言、CPU

SpringBoot 异步任务

hepingfly

Java springboot 异步任务

软件设计的基本原则

天天向上

架构师训练营第 1 期

架构师训练营 Week2 总结

lggl

总结 架构师训练营第一期

回首挑灯看剑谱 - Week2 - 学习总结

小粽

架构师训练营第二周作业

听夜雨

架构师训练营第 1 期

架构师训练营第 1 期 - 第二周学习总结

Anyou Liu

架构师训练营第 1 期

十大经典排序算法(动态演示+代码)

C语言与CPP编程

算法 编程语言 面试题 编译器、程序语言、CPU

知乎 iOS 客户端工程化工具 Venom-InfoQ