比如大名鼎鼎的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
得到结果:
Cartfile.resolved应该和Podflie.lock一个作用。
build了这么多平台实在太慢了,所以可以指定平台:
carthage build --platform iOS
将 Carthage/Build/iOS 中的 framework 文件添加到项目中。如图:
然后在 Build Phrases 中,点击左上角的 + 号,添加一个 New Run Script Phrase。如图:
使你的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这个插件。