最近把线上的项目依赖包管理工具从CocoaPods切换到Carthage上来,使用了一段时间有一些体会. 其实谈到iOS依赖包管理,我在切入CocoaPods时曾经也疑惑过,这个有些过度中心化包管理工具怎么就成为coding过程中的一个必选题,对现在为了降低开发成本越来越多可选择性工具和组件,秉承轻量、灵活、开放的理念做出的努力,反过来看CocoaPods其实就显得极为不友好. Rebuild等待模拟器效果时,你都会看到CocoaPods每次都会把所有第三方库都重新编译一次,而在这期间你只能傻傻的枯坐屏幕前。估计集成第三方库时很多人也会遇到类似错误提示diff: /Pods.lock: No such file一些错误提示。本来使用包管理目的,是为了降低集成第三方库手动操作的门槛更加方便、快捷,结果处理这些包管理的错误却又浪费了很多额外的时间。
使用了Carthage一段时间最大感受是极为灵活,且响应速度快、节约时间。所有的第三方库依赖,除非是更新的需要,rebuild时是不需要再次编译的,大大加快平常编译及 Archive 生成的时间。同时去中心化的好处是,每次都不需要向服务器获取最新库的索引这么个过程,这意味着每次配置和更新环境,只会去更新具体的库,节约请求和响应的时间。虽然去中心化,Carthage依赖于每个第三方库自己的源地址,也存在一些弊端,例如Pods Search第三库可能就不存在了,想查找第三方库的时候,因为没有一个中心服务器来帮助我们进行索引,则必须自己从网络上自行查找。相比这点不便,Carthage这种非侵入性的设计哲学,完成琐碎的部分,而把主要控制权交给开发者,反而大大放大其灵活性。当然了它与 CocoaPods 无缝集成,互不冲突。基本上使用Carthage之后就渐渐开始放弃CocoaPods。
安装与使用
官方在Github文档中给出三种方法. 很奇怪,我在Realse的最新版本0.16.2下载pkg文件一直未曾成功过,即时正常翻墙情况也无法正常下载这个pkg文件,留意下载链接指向了Amazon的云服务(如果没有猜错的话). 三种方法最为推荐还是Homebrew命令行方式来安装:
brew update
brew install carthage
因为我的Homebrow版本过低,第一次安装是采用brew update一直提示无法链接,导致直接更新时指向了2015年carthage的0.5.2版本(最新0.16.2):
其实卸载Homebrew重新安装即可. Carthage安装成功之后,找到项目根目录,创建一个Cartfile文件:
在Cartfile文件中引入一个第三方库,比如SwiftyJSON:
github "SwiftyJSON/SwiftyJSON"
退出自动保存文件之后,通过"carthage update" 命令执行:
carthage update
Carthage自动开始抓取并使用xcodebuild构建第三方库:
Fetching SwiftyJSON
Checking out SwiftyJSON at "2.3.3"
xcodebuild output can be found in/T/carthage-xcodebuild.KKIzNC.log
Building scheme "SwiftyJSON OSX" in SwiftyJSON.xcworkspace
Building scheme "SwiftyJSON iOS" in SwiftyJSON.xcworkspace
Building scheme "SwiftyJSON tvOS "in SwiftyJSON.xcworkspace
Building scheme "SwiftyJSON watchOS" in SwiftyJSON.xcworkspace
构建完成后,找到项目根目录,在项目的根目录中自动生成一个Carthage目录。这个目录中又包含了两个目录Build和Checkout. Build中存放的是构建好的framework包:
Checkouts中存放的是签出的第三方库项目源文件:
然后Xcode中打开项目找到General中最底部Linked Frameworks and Libraries,添加项目根目录中生成的Carthage中iOS的Framework文件:
除了这种方式,不过更好的办法是把 Carthage 编译的 Framework 路径加入到 Build Setting 中的 Framework Search Path中,基本设置完成后,正常编译通过,第三方库就集成到项目中.
顺带提一下项目根目录各个文件作用:
Cartfile文件用来标注需要哪些依赖库,对应版本或者 Git 分支,当然前提必须提交到Git。Cartfile.resolved文件用来跟踪项目当前所用的依赖版本号,主要为了保持多端开发一致。Carthage文件夹用来存放依赖库的源文件和编译后的文件 (不需要提交到 Git)。
利弊
虽然Carthage在实际项目比CocoaPods显得极为灵活,但库依然不如 CocoaPods 丰富:尽管很多库不需要声明并改造就直接可以被 Carthage 用,但依然有大量 CocoaPods 能用的库不支持。例如当你尝试使用Carthage在项目中集成Masonry时:
你会发现它提示并不支持. CocoaPods最新版本是 0.39.0,已经支持 iOS Frameworks,管理着共 10,822 个库,并且在不断增长中. Carthage 本身是由 Swift 语言写的,只支持动态框架,只支持 iOS8+,所以实际项目开发常态是CocoaPods和Carthage混合使用,还好Carthage能够项目与CocoaPods无缝集成,二者相互完美共存,互不干涉。CocoaPods 管理主要 Framework 的配置下,将少量其他 Framework 交给了 Carthage 管理也是不错的选择。
其实Carthage 只支持动态框架,它仅负责将项目 clone 到本地并将对应的 Cocoa Framework target 进行构建,之后你需要自行将构建好的 framework 添加到项目中。这也是剔除掉CocoaPods自动化后,所有的引入库的源和版本需要自己管理.
当然随着Swift越来越普及,未来的Swift Package Manager可能是一个更好的包管理方案。package Manager 实际上做的事情和 Carthage 相似,不过是通过llbuild(low level build system)的跨平台编译工具将 Swift 编译为 .a 静态库。因为苹果官方参与,所以以后可能会成为Xcode中一个标配。