Monorepo:Bazel和Cocoapods混和使用

背景

移動(dòng)端開發(fā)現(xiàn)狀

在組件化的浪潮下唇撬,公司引入多倉開發(fā)對(duì)工程架構(gòu)進(jìn)行解耦墩弯、跨業(yè)務(wù)技術(shù)能力復(fù)用吩跋,并輔以組件(混合)二進(jìn)制化進(jìn)行編譯提速。不過隨著工程規(guī)模增長渔工、業(yè)務(wù)復(fù)雜度提升锌钮,多倉二進(jìn)制的弊端日益凸顯:

  1. 合碼效率低下:多倉的引入使開發(fā)流程變復(fù)雜,最有代表性的合碼環(huán)節(jié)一次合碼涉及到主倉和多個(gè)組件引矩,每個(gè)組件要跑 Pipeline 流程進(jìn)行版本發(fā)布梁丘。這種模式提升了 CI 復(fù)雜度,降低了合碼效率旺韭。
  2. 依賴管理衍生問題:穩(wěn)定性差氛谜,多倉使環(huán)境依賴度變高,穩(wěn)定性變成多個(gè)倉庫穩(wěn)定性的乘積区端。需要手動(dòng)識(shí)別依賴層級(jí)值漫,先發(fā)版被依賴的庫,多版本并行開發(fā)時(shí)织盼,經(jīng)常發(fā)版失敗需要寫死依賴版本杨何。
  3. 代碼的可視性和可控性降低:跨組件重構(gòu)困難酱塔,全量靜態(tài)檢測無從入手,并且很難統(tǒng)一架構(gòu)規(guī)范危虱;本地開發(fā)體驗(yàn)差羊娃,工程代碼可信度低,無法直接對(duì)代碼進(jìn)行開發(fā)調(diào)試埃跷,本地開發(fā)需要更多的工具和流程來保證代碼的可視性和可控性蕊玷。
    誠然,多倉方案很好的落實(shí)了組件化思想捌蚊,但為解決上述多倉體系的問題,公司衍生了大量的優(yōu)化和效率工具近弟,其從結(jié)果看僅聚焦于解決局部問題缅糟,難以進(jìn)一步提升優(yōu)化空間。
目前頭條祷愉、抖音窗宦、B站、谷歌等公司采用了Monorepo的方案解決上述問題二鳄。

● 代碼復(fù)用:Monorepo 可以讓不同的項(xiàng)目或模塊共享代碼和依賴項(xiàng)赴涵,避免重復(fù)編寫和維護(hù)相同的代碼。
● 依賴管理:Monorepo 可以讓不同的項(xiàng)目或模塊共享依賴項(xiàng)订讼,避免依賴沖突和版本管理問題髓窜。
● 統(tǒng)一構(gòu)建:使用 Bazel 可以統(tǒng)一管理 Monorepo 中的構(gòu)建規(guī)則和依賴項(xiàng),提高構(gòu)建效率和可靠性欺殿。
● 版本控制:Monorepo 可以讓不同的項(xiàng)目或模塊共享版本控制系統(tǒng)寄纵,簡化版本管理和發(fā)布流程。

Monorepo 全源碼概念和優(yōu)缺點(diǎn)

Monorepo(Mono Repository)指的是將多個(gè)相關(guān)項(xiàng)目或模塊的代碼集中管理于一個(gè)倉庫的軟件開發(fā)模式脖苏。具體來說程拭,Monorepo 將所有的源代碼和配置文件等存儲(chǔ)在一個(gè)版本控制倉庫中,并使用相同的構(gòu)建和部署系統(tǒng)來管理和交付代碼棍潘。
全源碼(Full Source)是指將整個(gè)軟件系統(tǒng)的源代碼均存放于一個(gè)倉庫中恃鞋,源碼為單一可信源。
全源碼的概念通常與 Monorepo 聯(lián)系在一起亦歉,將概念定義為 Monorepo 全源碼解決方案恤浪,是區(qū)分于當(dāng)前流行的組件二進(jìn)制化開發(fā)模式。下圖中 MULTI-REPO 為前多倉開發(fā)模式肴楷,每個(gè)組件獨(dú)立 git 存儲(chǔ)资锰;MONO-REPO 為單倉模式,組件同主倉合并阶祭,只保留一個(gè) git绷杜。


image.png
優(yōu)點(diǎn):

● 便于代碼復(fù)用:所有項(xiàng)目代碼集中于單一倉庫直秆,相似的功能更便捷地抽象為公共庫,并直接由項(xiàng)目引用鞭盟。提高代碼的可維護(hù)性和開發(fā)效率圾结。
● 簡化依賴管理:無需依賴管理器,所有引用的依賴項(xiàng)都存在于同一代碼庫中齿诉,更加方便地進(jìn)行構(gòu)建和管理筝野。
● 原子提交:可以原子性地更改多個(gè)項(xiàng)目以避免多倉下不同版本依賴同步的兼容性問題。
● 大規(guī)模代碼重構(gòu):開發(fā)人員可訪問整個(gè)項(xiàng)目粤剧,從而更加容易地進(jìn)行代碼重構(gòu)歇竟,并確保每個(gè)部分都能正常工作。
● 跨團(tuán)隊(duì)協(xié)作:通過源代碼依賴改進(jìn)其他團(tuán)隊(duì)正在開發(fā)的項(xiàng)目抵恋,從而實(shí)現(xiàn)代碼所有權(quán)的靈活性焕议。
● 工程質(zhì)量提升:Monorepo 倡導(dǎo)開放,透明弧关,共享的組織文化盅安,有利于開發(fā)者成長,代碼質(zhì)量的提升世囊。

缺點(diǎn)

● 版本信息丟失:Monorepo 使用相同的版本號(hào)别瞭,無法對(duì)每個(gè)項(xiàng)目進(jìn)行單獨(dú)的版本控制。(多端同倉)
● 缺乏權(quán)限控制:無法根據(jù)需要授予對(duì)代碼庫的訪問權(quán)限株憾,所有代碼都在同一個(gè)項(xiàng)目中可能存在安全問題蝙寨。
● 磁盤空間占用:默認(rèn)情況下需檢出所有項(xiàng)目,需要更多的存儲(chǔ)空間嗤瞎。

為何選擇Bazel

參考Bazel中文網(wǎng)站

Bazel 是一種快速籽慢、正確可擴(kuò)展的構(gòu)建工具,具有集成測試功能猫胁,可在行業(yè)領(lǐng)先的生態(tài)系統(tǒng)中支持多種語言箱亿、代碼庫平臺(tái)

Bazel 速度快

Bazel 可以確切知道每個(gè)構(gòu)建命令需要哪些輸入文件弃秆,從而僅在一組輸入文件在每次構(gòu)建之間發(fā)生更改時(shí)重新運(yùn)行届惋,從而避免不必要的工作。 它會(huì)在同一計(jì)算機(jī)或遠(yuǎn)程構(gòu)建節(jié)點(diǎn)上以盡可能高的并行性運(yùn)行構(gòu)建命令菠赚。如果構(gòu)建結(jié)構(gòu)允許脑豹,它可以同時(shí)運(yùn)行數(shù)千個(gè)構(gòu)建或測試命令。

這受到內(nèi)存衡查、磁盤和遠(yuǎn)程構(gòu)建農(nóng)場(如果有)的多個(gè)緩存層支持瘩欺。在 Google,我們通常會(huì)將緩存命中率達(dá)到 99% 以上。

Bazel 正確

Bazel 可確保您的二進(jìn)制文件僅基于您自己的源代碼構(gòu)建俱饿。Bazel 操作在單獨(dú)的沙盒中運(yùn)行歌粥,Bazel 會(huì)跟蹤構(gòu)建的每個(gè)輸入文件,并且只會(huì)在需要時(shí)重新運(yùn)行構(gòu)建命令拍埠。這樣可以使您的二進(jìn)制文件保持最新狀態(tài)失驶,以便相同的源代碼始終生成相同的二進(jìn)制文件

對(duì)無休止的 make clean 調(diào)用枣购,以及追尋實(shí)際上在從未被構(gòu)建的源代碼中解決的幽靈 bug 的說辭嬉探。

Bazel 具有可擴(kuò)展性

自行編寫規(guī)則和宏,針對(duì)各種項(xiàng)目的特定需求自定義 Bazel棉圈,從而充分發(fā)揮 Bazel 的功能涩堤。

Bazel 規(guī)則是使用 Starlark 編寫的,Starlark 是我們的內(nèi)部編程語言分瘾,是 Python 的子集胎围。Starlark 讓大多數(shù)開發(fā)者能夠使用規(guī)則編寫功能,同時(shí)還能創(chuàng)建可在整個(gè)生態(tài)系統(tǒng)中使用的規(guī)則芹敌。

遷移構(gòu)建系統(tǒng)Bazel

參考Build an iOS App

  1. 遷移至 Bazel 體系痊远,配置BUILD和WORKSPACE
  2. 兼容同時(shí)使用cocoaPods和Bazel
  3. .podspec轉(zhuǎn)BUILD 開源方案
  4. install.sh 腳本改造

最終目錄如下:


image.png

cocoapods生成的工程叫Test1Bazel.xcworkspace垮抗,Bazel生成的工程叫:xxxxxBazel.xcodeproj

Build文件:

load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")

swift_library(
    name = "lib",
    srcs = glob(["Sources/Delegate/*.swift"]),
    data = [
        "Resources/Main.storyboard",
    ],
    deps = ["http://Sources/Network:AFNetworking"],
)

ios_application(
    name = "xxxxxxBazel",
    bundle_id = "com.wuwei.swift",
    app_icons = glob(["Assets.xcassets/AppIcon.appiconset/**"]),
    families = [
        "iphone",
    ],
    infoplists = ["Resources/Info.plist"],
    launch_storyboard = "LaunchScreen.storyboard",
    minimum_os_version = "14.0",
    visibility = ["http://visibility:public"],
    deps = [":lib"],
)

load(
    "@rules_xcodeproj//xcodeproj:defs.bzl",
    "top_level_target",
    "xcodeproj",
)

xcodeproj(
    name = "xcodeproj",
    build_mode = "bazel",
    project_name = "xxxxxxBazel",
    tags = ["manual"],
    top_level_targets = [
        ":xxxxxxBazel",
    ],
)

管理工程依賴
CocoaPods 在多倉模式下除去自身的依賴管理能力外氏捞,承擔(dān)了非常多的非自身功能,
如組件二進(jìn)制集成冒版、hmap 的編譯優(yōu)化液茎,混編能力的支持。
遷移 Bazel 構(gòu)建系統(tǒng)后這些優(yōu)化能力名正言順的通過構(gòu)建系統(tǒng)來承擔(dān)辞嗡。
在 Monorepo 生態(tài)中我們也應(yīng)該設(shè)立相應(yīng)的組件依賴關(guān)系驗(yàn)證及組件模塊分層服務(wù)捆等。Bazel 可以設(shè)置所有 target 的可見域,開發(fā)者可以將 target 標(biāo)記為私有续室,以防止被其他項(xiàng)目錯(cuò)誤地依賴栋烤,這種約束幫助我們規(guī)范代碼倉庫之中各個(gè)庫之間的依賴關(guān)系。

優(yōu)化本地體驗(yàn)
在本地開發(fā)中通過開源工具 Tulsi挺狰、BuildService明郭、IndexImport 的定制化開發(fā),補(bǔ)齊 Xcode 體系中索引丰泊、高亮薯定、日志、進(jìn)度條等語言能力瞳购,使 Xcode 體驗(yàn)與之前無異话侄。通過這些工具我們把 Xcode 的優(yōu)化牢牢把握在自己的手上,也很好的提升了 Xcode 易用性。
Tulsi已經(jīng)不維護(hù)了年堆,官方推薦rules_xcodeproj

最后

Bazel生成的Xcode工程里面的Build settings配置項(xiàng)需要額外的腳本快速配置吞杭,因?yàn)锽uild文件改動(dòng)后Xcode工程每次需要重新生成,手動(dòng)修改不現(xiàn)實(shí)嘀韧。

最后的最后篇亭,我想說:我最大的愿望是世界和平!锄贷!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末译蒂,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谊却,更是在濱河造成了極大的恐慌柔昼,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炎辨,死亡現(xiàn)場離奇詭異捕透,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)碴萧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門乙嘀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人破喻,你說我怎么就攤上這事虎谢。” “怎么了曹质?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵婴噩,是天一觀的道長。 經(jīng)常有香客問我羽德,道長几莽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任宅静,我火速辦了婚禮章蚣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姨夹。我一直安慰自己纤垂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布匀伏。 她就那樣靜靜地躺著洒忧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪够颠。 梳的紋絲不亂的頭發(fā)上熙侍,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼蛉抓。 笑死庆尘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巷送。 我是一名探鬼主播驶忌,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼笑跛!你這毒婦竟也來了付魔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤飞蹂,失蹤者是張志新(化名)和其女友劉穎几苍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陈哑,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妻坝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惊窖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刽宪。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖界酒,靈堂內(nèi)的尸體忽然破棺而出圣拄,到底是詐尸還是另有隱情,我是刑警寧澤盾计,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布售担,位于F島的核電站赁遗,受9級(jí)特大地震影響署辉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岩四,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一哭尝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧剖煌,春花似錦材鹦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茉兰,卻和暖如春尤泽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工坯约, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熊咽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓闹丐,卻偏偏與公主長得像横殴,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卿拴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容