Carthage和iOS元件二進位制化

weixin_34194087發表於2017-05-19

比如大名鼎鼎的ReactCocoa。切到早期版本,你根本找不到podspec,說明它從未官方支援過CocoaPods。現在的ReactiveCocoa.podspec都是第三方發的。而從2.4.1起ReactCocoa開始使用Carthage。

再比如Mantle也是一樣。Mantle更是直接在README中這樣說:

If you would prefer to use CocoaPods, there are some Mantle podspecs that have been generously contributed by third parties.

那麼我們來講講Carthage

Carthage翻譯過來就是“迦太基”(Qart-ḥadašt,該詞源於腓尼基語,意為“新的城市”,英語:Carthage)的意思。我猜取這個名字大概取“新的城市”這個寓意吧。

Carthage是個後起之秀,從2014年10月開始。而CocoaPods資格更老一些,從2011年8月就開始了。從start來看,CocoaPods是8262;Carthage是7397。他們已經在一個數量級了。說明Carthage相比CocoaPods並不差。Carthage肯定是為了解決CocoaPods的某些問題而生。

檢視Carthage的README。首先看到的是workflow。

1.Create a Cartfile that lists the frameworks you’d like to use in your project.

2.Run Carthage, which fetches and builds each framework you’ve listed.

3.Drag the built .framework binaries into your application’s Xcode project.

第一步建立一個Carfile列出你想要的庫。
這個CocoaPods一樣。

第二步執行Carthage,它會拉去和編譯每一個庫。
說明還是需要編譯一遍的。

第三步把framework拽進專案。

需要注意的還有這個:

Once you have Carthage installed, you can begin adding frameworks to your project. Note that Carthage only supports dynamic frameworks, which are only available on iOS 8 or later (or any version of OS X).

Carthage只支援動態庫,所以只支援到iOS 8。

看一下Carthage自己的說明,它和CocoaPods的區別。

CocoaPods is a long-standing dependency manager for Cocoa. So why was Carthage created?

Firstly, CocoaPods (by default) automatically creates and updates an Xcode workspace for your application and all dependencies. Carthage builds framework binaries using xcodebuild, but leaves the responsibility of integrating them up to the user. CocoaPods’ approach is easier to use, while Carthage’s is flexible and unintrusive.

關鍵詞:binaries、integrating、flexible、unintrusive。

  • Carthage使用二進位制。
  • 使用者自己整合進去。
  • 更靈活。
  • 非侵入。

The goal of CocoaPods is listed in its README as follows:

… to improve discoverability of, and engagement in, third party open-source libraries, by creating a more centralized ecosystem.

By contrast, Carthage has been created as a decentralized dependency manager. There is no central list of projects, which reduces maintenance work and avoids any central point of failure. However, project discovery is more difficult—users must resort to GitHub’s Trending pages or similar.

Carthage是個分散型的依賴管理器。降低了維護工作和避免了集中管理的問題。CocoaPods是個集中的生態系統。

Ultimately, we created Carthage because we wanted the simplest tool possible—a dependency manager that gets the job done without taking over the responsibility of Xcode, and without creating extra work for framework authors. CocoaPods offers many amazing features that Carthage will never have, at the expense of additional complexity.

最後,我們建立Carthage是為了創造一個更簡單的工具。建立一個依賴管理器去完成工作,而不用接手Xcode的職責。

CocoaPods提供了很多很棒的功能,Carthage永遠不會以額外的複雜性作為代價去提供這些功能。貌似這句才是最關鍵。

試用一下Carthage

安裝:

brew install carthage

當前預設安裝版本是0.11.0

建立Cartfile:

# Require version 2.3.1 or later
github "ReactiveCocoa/ReactiveCocoa" >= 2.3.1

# Require version 1.x
github "Mantle/Mantle" ~> 1.0    # (1.0 or later, but less than 2.0)

執行carthage update

*** Cloning Mantle
*** Cloning ReactiveCocoa
*** Cloning Result
*** Cloning Nimble
*** Checking out ReactiveCocoa at "v4.2.2"
*** Checking out Result at "2.1.3"
*** Checking out Mantle at "1.5.8"
*** Cloning Quick
*** Cloning xcconfigs
*** Cloning Box
*** xcodebuild output can be found in /var/folders/w2/khz8t6h10q51lx_hvw8ds9wr0000gn/T/carthage-xcodebuild.Wwng0O.log
Failed to discover shared schemes in project Nimble.xcodeproj—either the project does not have any shared schemes, or xcodebuild never returned

If you believe this to be a project configuration error, please file an issue with the maintainers at https://github.com/Mantle/Mantle/issues/new

竟然失敗了。
執行:

sudo rm -rf ~/Library/Caches/org.carthage.CarthageKit
carthage build

得到結果:


6109616-55c9c853802b39ac.png
carthagebuild

Cartfile.resolved應該和Podflie.lock一個作用。

build了這麼多平臺實在太慢了,所以可以指定平臺:

carthage build --platform iOS

將 Carthage/Build/iOS 中的 framework 檔案新增到專案中。如圖:


6109616-c6860fa868cc902c.png
carthageaddframework

然後在 Build Phrases 中,點選左上角的 + 號,新增一個 New Run Script Phrase。如圖:


6109616-b60f0bc4cf14e80d.png
carthagerunscript

使你的framework支援Carthage

1.明確只最低支援iOS8。
2.共享你的Xcode schemes。Carthage會build你共享的Xcode schemes。
3.解決編譯的錯誤。
4.打上tag釋出(上傳到程式碼庫)。
5.Carthage可以使用你預先生成的包含frameworks的zip檔案,這樣就不用在使用者這邊編譯了。這個zip檔案必須包含在你釋出的tag中。

私有Carthage

其實很簡單,釋出到你自己的程式碼源,然後在Cartfile裡面這樣寫就可以了:

git "https://gitlab.baidao.com/git-error-translations2.git"  >= 1.0.1

看了下其他文件和親身使用經歷。總結一下:

  • Cartfile配置起來很簡單。
  • 使用Carthage,版本管理是不用擔心的。和CocoaPods類似。
  • Cartfile不能載入深度依賴。比如有個庫KKNetKit依賴AFNetwork。你不能只寫KKNetKit,還得顯示地寫上AFNetwork。這一點和CocoaPods不同,CocoaPods會自動幫你加入AFNetwork。
  • Carthage和你的專案並沒有直接的關係。這也符合了它宣稱的非侵入。你可以在任意地方定義Cartfile。
  • Carthage一樣可以使用CI。例如travis CLI
  • 目前Carthage的CLI相比CocoaPods還是做的比較爛的。也沒有很多功能。
  • 現在支援Carthage的常用第三方庫並不是很多。Carthage目前也沒有像CocoaPods那樣提供一個search命令去查詢庫。所以我並不能知道有哪些第三方庫支援了Carthage。
  • 它會自動建立submodule。這個專門放submodule資料夾叫Carthage/Checkouts。
  • 因為是非侵入式的,需要自己手動去配置Xcode。這個有好處也有壞處。如果用到了很多庫,會感覺麻煩。
  • 如果你有多個App的話,共用那些framework會非常爽。但因為需要這樣配置"$(SRCROOT)/Carthage/Build/iOS/Mantle.framework",你的本地路徑可能和其他人會不一樣,所以沒法在團隊間共享。
  • 我要除錯原始碼的話就變的比較麻煩。檢視原始碼可以在submodule中去找,但增加了麻煩。
  • 首次carthage update時間會非常長。雖然我只是匯入了2個庫而已。(那2個庫沒有提供archive zip)
  • 因為時間非常長,所以就得考慮如何在Team中共享的問題。讓每個人都xcodebuild一遍時間太長了,上傳到git又太大了。
  • 當用CocoaPods時,pod install之後需要重新編譯所有CococaPods庫,哪怕我只改動了一個CocoaPods庫的版本號。而Carthage也不能解決這個問題。carthage update和carthage build也都會重新編譯一遍。而Carthage更慢,因為CocoaPods只要編譯一個architect,Carthage要編譯多個Architect。
  • 如果那個Carthage的目標庫沒有提供archive zip的話,還是需要編譯一次。Team其他人也需要編譯一次。如果要徹底避免的話,當一個人編譯完,需要把frameworks都上傳到程式碼庫上才行。或者自己壓個zip,內網互相傳送一下?
  • 就算Carthage目標庫支援archive zip,他一定得支援全部平臺,問題是我怎麼告訴它我只需要iOS平臺的呢?全部clone下來,就中國這個網路環境豈不是很痛苦。

Carthage的優缺點都是非常鮮明的,所以需要綜合自身的情況考慮。

那用Carthage做元件二進位制化可不可以?

我覺得是可以的。但有以下幾個問題需要解決。

  • 遷移的成本。一般大家都是用的CocoaPods。
  • 只支援到iOS8。如果支援到iOS7的就沒有辦法了。
  • 沒有靈活的方式去切回原始碼除錯。檢視原始碼也不是很方便,畢竟不在一個workspace裡面。
  • 目前支援的第三方庫並不多。沒有像CocoaPods那樣普及。

我的建議是:CocoaPods和Carthage一起用。

Carthage解決了元件如何二進位制化的問題,加快了編譯速度。在開發時繼續使用CocoaPods可以檢視弱業務元件和基礎功能元件的原始碼、以及除錯原始碼。第三方庫視情況而定,如果它支援Carthage就用Carthage。

具體做法是:在App主專案中,業務元件都是Carthage提供archive zip的方式整合進來的。而在業務元件A的Example App中還是可以繼續使用CocoaPods載入弱業務元件和基礎功能元件和不支援Carthage的第三方元件。參與整合除錯的其他業務元件和支援Carthage的第三方庫可以通過Carthage整合進來。

這篇文章只是提供了一種思路。如果你原先一直使用CocoaPods又沒有迫切二進位制化的需求的話,我覺得目前可以不考慮轉用Carthage。

即使你有二進位制化需求的話,也可以參考我寫的這篇文章。推薦還是使用CocoaPods加cocoapods-packager這個外掛。

相關文章