日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS之CocoaPods二进制化的实现方案

發布時間:2024/5/21 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS之CocoaPods二进制化的实现方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

  • 隨著公司業務規模的增長,iOS 客戶端的代碼量也越來越大,編譯一次項目的時間也越來越長。那么減少編譯時間成了一個不得不面對的問題;
  • 隨著越來越多方便的第三方組件,現在開發App基本十多個第三方依賴以上。沒有build cache 或者打正式包的時候,每次基本耗時10分鐘以上;
  • 現有的二進制方案如 Carthage、Rome 等都是在本地生成 framework,沒法實現“一次編譯,處處使用”的目標;
  • 主要原因是需要編譯大量源文件(大概分為 App 和 Cocoapods 依賴庫),所以把可抽離代碼編譯好,再去引用就能減少源文件編譯時間;
  • 為了實現這個目標,就需要一個人或者一個 CI Job,把編譯好的二進制產物上傳到某個的地方,集中化地管理這些二進制形式的依賴。然后在每個人 pod install 的時候,檢查該 pod 版本對應的二進制是否存在,如果有就使用,沒有就繼續采用源碼的方式依賴;
  • 這個方案隱藏了許多細節,比如到底應該如何集中管理這些 pod,如何知道對應的版本是否存在,如何在 pod install 的時候動態地把這些 pod 從源碼形式的依賴換成二進制形式的依賴等;
  • 整個流程涉及生產方(產生二進制)和消費方(使用二進制)。

思路流程

一、產生二進制
① 代碼結構
  • 產生二進制的流程在一個 CI Job 中,每隔一段時間,它會同步主倉庫最新的 dev 分支,然后運行管理此環節的工具,Platypus;
  • 結構如下:

  • 說明:
    • config.yml 是與工程相關聯的配置,其中包含了需要二進制化的名單(pod_names),project 文件相關信息,以及工程初始化的 action(prebuild_action)等等。
    • specs_repo 是私有的 podspec 倉庫,需要單獨創建,負責集中管理已經二進制好的 pod 信息。
② 具體流程

  • (a)對于大多數項目來說是 pod install,但如果在不改變 podfile 原有寫法的基礎上實現此套方案,需要把使用 patch 過后的 pod install 方式。
  • (b)白名單存在的意義有兩點:
    • 一是有些 pod 本來就是二進制好了的;
    • 二是某些 pod 因為頭文件沒有用 < > 的方式引用在目前階段沒法二進制,否則就會因為找不到頭文件編譯失敗;
  • ( c )模擬器和真機的版本都需要編譯,最終使用 lipo 把兩份二進制合并到一個 .framework 中。如果 pod 中包含 Swift 代碼,需要把模擬器和真機的編譯產物中的 swiftdoc 和 swiftmodule 都合并到一個文件夾中。由于 Swift 版本的原因,由舊版 Xcode 編譯生成 Swift 二進制是無法在新版 Xcode 中使用的;
  • (f)通過 CocoaPods 中的 Analyzer 調用 analyzer.analyze.specifications,可以獲取當前項目所有依賴 pod 的 podspecs,具體操作可以參考該文章:分析使用 CocoaPods 項目的依賴;關于如何編輯 podspec,可以使用這個 gem。編輯的內容包括刪掉 source_files 字段,把 vendored_frameworks 字段指向 .framework, source 指向上傳生成的 URL, resources 指向對應 .framework 中的資源等。保存后,作為二進制時依賴使用的 podspec;
  • (g)這一步是為了把項目中依賴的 pod 版本與二進制化后的版本建立起聯系。因為項目中依賴的引用方式五花八門,有用 CocoaPods Master Repo 中版本號的,有用 git tag 的,也有用 git commmit 的,針對不同的引用方式,都要有對應的匹配規則;
③ 示例說明
  • (g) 示例說明:比如有一個使用 tag 方式引用的組件,把它的 tag 號后面加上 -yang-static 作為它在私有 Specs 倉庫中的版本號,它在 podfile 中的 external_source 作為 summary 字段,同時確保唯一性。這里的映射關系只要能一一對應起來,隨便怎么建立都好,如下:
pod 'A', git: 'git@git.xxx.com:xxx/A.git', tag: '4.24.0.9'
  • 所以它被改完版本號后 poddpec 會變成如下樣式:
{"name": "A","version": "4.24.0.9-yang-static","summary": "{:git=>\"git@git.xxx.com:xxx/A.git\", :tag=>\"4.24.0.9\"}"...}
  • (h) Specs 倉庫目錄結構如下所示,目錄均為手動創建,沒有使用 CocoaPods 提供的方式更新:
├── A│ └── 4.22.0.8-yang-static│ └── A.podspec.json├── B│ ├── 0.2.21-yang-static│ │ └── B.podspec.json│ └── 0.2.9-yang-static│ └── B.podspec.json├── C│ └── 1.4.0-yang-static│ └── C.podspec└── D└── 2.5.0-yang-static└── D.podspec
二、使用二進制
  • 在觸發 pod install 過程之前,需要在本地把私有 Specs 倉庫更新到最新,pod repo update xxx;
  • 接下來就是 patch pod install 替換依賴的過程,在不更改 podfile 的情況下,只能模仿 pod install 的過程,自己創建一個腳本來替代這個操作。整個過程不復雜,可以參考下面這一段帶注釋的代碼:
# 參考 `CocoaPods` 的源碼,模擬 `pod install` 執行的過程argv = CLAide::ARGV.new([])cmd = Pod::Command.new(argv)cmd.send :verify_podfile_exists!installer = cmd.send :installer_for_configinstaller.repo_update = falseinstaller.update = falsepodfile = installer.podfile# 獲取此次 install 的配置,是全部使用二進制還是全部使用源碼# 全部使用二進制時,哪些 pod 依舊使用源碼引入use_all_binary, source_pod_list = ZHPodInstallHelper.read_binary_pods_prefuse_all_binary = false if ENV['ALL_SOURCE'] == 'true'unless use_all_binaryputs ' pod install with all source'installer.install!exit(0)end# 為 podfile 添加二進制 Specs 倉庫的 sourcepodfile.send(:get_hash_value, 'sources')hash_sources = podfile.send(:get_hash_value, 'sources') || []hash_sources << 'git@git.xxx.com:xxx/E.git'podfile.send(:set_hash_value, 'sources', hash_sources.uniq)# 遍歷 podfile 中的所有 dependenciespodfile.root_target_definitions.each do |root_target_definition|children_definitions = root_target_definition.recursive_childrenchildren_definitions.each do |children_definition|dependencies_hash_array = children_definition.send(:get_hash_value, 'dependencies')next if dependencies_hash_array.count.zero?dependencies_hash_array.each do |dependencie_hash_item|next if dependencie_hash_item.class.name != 'Hash'dependencie_hash_item.each do |name, value|next if value[0].is_a?(Hash) && value[0][:path]search_name = namesearch_name = name.split('/')[0] if name.include?('/')# 對于想要以源碼依賴的 pod,不作修改next if source_pod_list.include?(search_name)# 根據 podfile 中引用的源碼版本,在私有 Specs 倉庫中查找相應二進制的版本version = ZHPodInstallHelper.get_binary_version(search_name, value[0].to_s)# 存在對應的二進制版本,就替換掉dependencie_hash_item[name] = [version] if versionendend# 替換 podfile 的 dependencies 為修改后的 dependencieschildren_definition.send(:set_hash_value, 'dependencies', dependencies_hash_array)endendinstaller.install!

局限

  • 需要自定義 pod install 過程,同時修改某些 CocoaPods 中的私有屬性;
  • 最終的 binary size 會比使用源碼的時候大一點,不建議最終上傳 Store 的時候使用;
  • 缺少一個驗證的機制,如果已發布的二進制包不能被項目正常引用,那么會導致所有人的編譯失敗;
  • 由于工程采用的是全部靜態庫依賴的形式,所以在二進制和源碼切換的過程中會對 project 文件產生更改。

步驟總結

① 打包第三方源碼
  • git clone各種組件源碼庫;
  • 腳本打包:
    • tag拉分支, 并切換(打包之后刪除, 再回去master);
    • 使用pod gen根據podsec創建工程;
    • xcodebuild打包framework(真機和模擬器);
    • 合并真機和模擬器的framework;
    • 實踐的時候會發現有些庫是不能通用一個腳本的;
  • 上傳framework(用了binary-server管理);
② 二進制的podsec上傳到私有的repo
  • 使用pod bin spec create創建二進制版本的podsec;
    • 有subsec的會要求提供template;
    • 某些平臺要求版本會低于8, 因為是使用framework, 需要平臺版本需要改為8以上;
  • 上傳生成的podsec;
③ 使用
  • 在Podfile加上source {私有repo},然后再加一個官方的repo(例如: source ‘https://cdn.cocoapods.org/’)。
  • 官方的一定要加在后面,有相同的庫會根據source的順序獲取依賴,想切回源碼注釋私有庫那一行就好了(因為只是簡單的一個私有二進制repo)。

輔助工具

  • cocoapods-bin
  • binary-server

總結

以上是生活随笔為你收集整理的iOS之CocoaPods二进制化的实现方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。