iOS 輕量級包管理工具Carthage瞭解下

Why Carthage?

我們已經熟知Cocoapods了,對於工程來說,幫我們自動創建Xcode WorkSpace和所有的依賴,對於依賴庫來說,用來做本地local pod或者遠程pod都非常好用,我們只要編寫好對應的podspec文件,Cococapods會幫我們生成所有的依賴配置集成到項目。可以認爲他是一體機,入侵性的幫我們管理好了Xcode項目文件。對於不需要手動管理的同學,這已經是一個長期好用的工具了,那爲什麼還要有Carthage呢?

1、去中心化管理工具
沒有集中的podspec倉庫管理過程,可以減少維護工作以及集中倉庫掛掉的問題,每次只要更新對應的庫即可。

2、DIY 手動集成
Checkout項目到指定目錄,根據當前下載的源碼默認直接編譯成二進制用xcodebuild,這個和podpackage一樣,問題是這個維護的問題,因此我們這邊開始瞭解新的構建工具。對於編譯的二進制庫,用戶手動導入項目使用。對於會用的同學來說,這簡直就是松耦合的過程,但是對於依賴Cocoapods的朋友,這會覺得很麻煩,畢竟DIY的過程對不同的朋友來說感受是不同的。對我來說,我要的就是這個Carthage Build的這個工具,本文就簡單介紹下全過程。

3、對框架作者無感
Carthage想盡可能簡單的做一個項目管理工具,他不會參與承擔Xcode的構建過程,也不會對框架的開發者帶來額外的工作。雖然Cocoapods給框架帶來了非常強大的集成功能,但是前提是要爲你的庫編寫對應的podspec文件,比如包括project元數據,以及告訴他如何進行依賴編譯,這些功能Carthage官方說的是不會有,我們是非侵入性的,代價是需要手動管理依賴和配置。

4、提高編譯速度
根據上面的三點,有個很好的消息是,他能和Cocoapods無縫銜接,兩者可以共存,而且幫我們編譯好了二進制,對於一些編譯很長時間的庫打包成二進制,或者不常用的庫打包成二進制,存入文件服務器,寫好podspec指向zip包,然後結合Podfile文件進行依賴管理,同時可以結合CI優化編譯和打包時間。

Carthage 安裝

  • 手動:從release中下載對應的Carthage.pkg,然後根據介紹安裝。如果你通過CLI安裝了pkg,可能還需要執行sudo chown -R $(whoami) /usr/local
  • Homebrew: 通過brew安裝,先執行brew update更新下倉庫,然後brew install carthage即可。但是如果你之前安裝過二進制版本,你應該從/Library/Frameworks/CarthageKit.framework這裏把文件移除。

給你的App添加Carthage生成的Framework

  • 1.Carthage 文件創建

首先用Xcode創建一個簡單的CarthageDemo1工程

cd ~/Desktop/CarthageDemo1
touch Cartfile

在文件中輸入內容如下

github "AFNetworking/AFNetworking" == 3.1.0
github "Masonry/Masonry" == 0.6.3
github "YYModel/YYModel"

該文件就和Cocoapods中的Podfile是一樣的,他支持三種類型GitHub repositories, Git repositories, 和 binary-only frameworks served over https
GitHub repositories

github "ReactiveCocoa/ReactiveCocoa" # GitHub.com
github "https://enterprise.local/ghe/desktop/git-error-translations" # GitHub Enterprise

github指定owner/repo的格式

Git repositories
這個也是我們最熟知的git地址

git "https://enterprise.local/desktop/git-error-translations2.git"

Binary only frameworks
支持編譯好的二進制.framework,兼容httpsfile://

binary "https://my.domain.com/release/MyFramework.json"   // Remote Hosted
binary "file:///some/Path/MyFramework.json"               // Locally hosted at file path
binary "relative/path/MyFramework.json"                   // Locally hosted at relative path to CWD
binary "/absolute/path/MyFramework.json"                  // Locally hosted at absolute path

對應的json二進制工程spec

{
	"1.0": "https://my.domain.com/release/1.0.0/framework.zip",
	"1.0.1": "https://my.domain.com/release/1.0.1/framework.zip"
}

json文件必須是版本和zip地址的對應,不能用branchs,tags,commit,也就是在你打包好的二進制工程中,做個json文件,版本指向遠程https文件服務器或者lfs管理的zip地址即可。

以上三種方式制定的地址,後面可以和Podfile一樣跟版本號 ==,->,~>,這三個和Cocoapods是一樣的,就不展開了。

  • 2.安裝依賴
carthage update --platform iOS --no-use-binaries

官方介紹是沒有後面的可選參數的,--platform iOS是指定平臺默認是全平臺架構的,--no-use-binaries是不用預編譯的二進制,用源碼重新編譯二進制,如果不指定,網絡不好的情況下一直會出現如下錯誤

***  Skipped installing Masonry.framework binary due to the error:
	"GitHub API request failed: networkError(Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to 
	the server." UserInfo={NSUnderlyingError=0x7fdc00c1e8a0 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 "
	(null)" UserInfo={_kCFStreamErrorCodeKey=61, _kCFStreamErrorDomainKey=1}}, 
	NSErrorFailingURLStringKey=https://api.github.com/repositories/11570469/releases/tags/v0.6.3, 
	NSErrorFailingURLKey=https://api.github.com/repositories/11570469/releases/tags/v0.6.3, 
	_kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=61, NSLocalizedDescription=Could not connect to the 
	server.})"

    Falling back to building from the source

如果想了解更多,可使用carthage help update查看。如果只需要更新某個第三方庫

carthage update xxxxxx --platform iOS

當命令執行完之後,Cartfile同級目錄下會出現一個Carthage文件夾和Carthage.resolved文件。打開Carthage文件夾,我們會看到BuildChekouts文件夾。Carthage.resolved文件夾類比就是Podfile.lock用來鎖定版本信息的。一般團隊開發,我們會把這個文件提交到倉庫,避免出現不同同學安裝不同的依賴。carthage update其實就是carthage buildcarthage checkout的集合,因此會生成上述提到的兩個文件夾。Build目錄下放置編譯好的默認動態庫,checkouts默認放置檢出的源碼。

  • 3.添加Framework到項目中

打開Xcode項目,選擇Target->General選項卡,然後再底部找到Linked Frameworks and Libraries。打開項目根目錄下Carthage/Build/iOS,找到你需要的Framework,然後把這幾個庫拖進來。這邊我用Swift更新的時候死活更新下來,就用OC的兩個庫代替了,反正也就是對應的AlamofireSnapKit這兩個庫
請添加圖片描述
請添加圖片描述

然後找到target->build phase選項卡,添加一個New Run Script Phase,然後添加新的腳本/usr/local/bin/catthage copy-frameworks。點擊下面的Input Files,給對應的庫添加。
在這裏插入圖片描述
這裏在目錄下創建了一個input.xcfilelistoutput.xcfilelist,在input下面添加

$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
$(SRCROOT)/Carthage/Build/iOS/Snapkit.framework

output下添加

$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Alamofire.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SnapKit.framework

這裏添加output的目的是爲了提高編譯速度。只有當input變化的時候或者output文件不存在的時候,纔會在編譯的時候執行copy-framework的腳本。

以上的操作,就可以愉快的進行代碼編寫了。

如果出現以下報錯,是因爲部署以你App的第三方庫編譯的時候選擇了Code Coverage,比如AFNetworking,因此我們需要給對應的工程也添加,或者庫編譯成二進制的時候自己手動勾選去掉

Undefined symbols ___llvm_profile_runtime

方法1、-fprofile-instr-generate to Build Settings > Linking > Other Linker Flags
方法2、Edit Scheme -> Test -> Options -> Code Coverage

製作自己的Carthage庫

經常製作Cocoapods庫的同學對podspec文件那應該相當熟悉了,每次都要編寫,那麼Carthage就相當簡單了。同樣用Cocoapods的方式測試一下
1、新建一個動態庫

pod lib create JXLiveManager

在這裏插入圖片描述
Carthage編譯的時候是根據.xcodeproj(這裏是xcworkspace)的shared scheme來查找的,因此我們在Manager Schemes中,需要把對應的scheme勾選爲Shared。

這裏可以看到,xcworkspace下,JXLiveManager對應的工程下有一個JXLiveManager-Example工程可以編譯,Pods下就有三個可以編譯的文件,其中JXLIveManager默認是動態庫,其他兩個都是靜態庫,稍後編譯產物可以看到,您也可以再mach-o中查看。

如果你想讓所有的Scheme都能編譯成功

cd Example 
carthage build --no-skip-current

此時會生成一個Carthage/Build的文件夾,裏面可以查看編譯完成後的二進制文件,區分動態庫和靜態庫

2、解決編譯失敗問題
當你執行carthage build --no-skip-current如果失敗了,沒有編譯產物,試着跑一下xcodebuild -scheme SCHEME -workspace WORKSPACE build 或者執行 xcodebuild -scheme SCHEME -project PROJECT build,看看是否會出現一樣的錯誤,控制檯能打印出詳細的信息進行調試。如果你有多個版本的Xcode,直接修改即可Xcode-->Preference-->Locations-->Command Line Tools修改即可。

3、Release
以上兩步操作後,沒有問題的話,就可以和Cocoapods一樣提交了,只是這裏不需要驗證podspec文件了,直接推入遠程倉庫即可。不過記得打tag

4、Archive

mikejingdeMBP:Example MKJ$ carthage archive JXLiveManager
*** Found Carthage/Build/iOS/JXLiveManager.framework
*** Found Carthage/Build/iOS/JXLiveManager.framework.dSYM
*** Found Carthage/Build/iOS/JXLiveManager.framework
*** Found Carthage/Build/iOS/JXLiveManager.framework.dSYM
*** Found Carthage/Build/iOS/2EC988C1-5947-3677-8933-C1AFA435AAD9.bcsymbolmap
*** Found Carthage/Build/iOS/C91C35F6-77D9-3CBE-A763-20B45F917C22.bcsymbolmap
*** Found Carthage/Build/iOS/8D3101C1-A4B1-3685-B908-07F98610864F.bcsymbolmap
*** Found Carthage/Build/iOS/8D3101C1-A4B1-3685-B908-07F98610864F.bcsymbolmap
*** Found Carthage/Build/iOS/C91C35F6-77D9-3CBE-A763-20B45F917C22.bcsymbolmap
*** Found Carthage/Build/iOS/2EC988C1-5947-3677-8933-C1AFA435AAD9.bcsymbolmap
*** Found Carthage/Build/iOS/F409B1FF-32B1-3DA3-B6CD-4660A474960E.bcsymbolmap
*** Found Carthage/Build/iOS/F409B1FF-32B1-3DA3-B6CD-4660A474960E.bcsymbolmap
*** Created JXLiveManager.framework.zip

正常情況下,前三步驟已經完全可以了,但是如果你要在提交的時候預編譯打包成zip也可以執行archive命令,Carthage會在當前目錄下把二進制產物打包成zip。可以方便後續的CI集成或者Binary only frameworks的json編寫

後續

上面先對比了Cocoapods,然後集成到項目做了測試,最後用自己做的第三方庫做了Demo。那麼上面提到的都是默認的動態庫製作,由於一般我們的項目都還是Cocoapods管理的,而且過多的動態庫會影響啓動時間,下一個文章將記錄下如何優雅的用Carthage打包靜態Framework

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章