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,兼容https和file://
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文件夹,我们会看到Build和Chekouts文件夹。Carthage.resolved文件夹类比就是Podfile.lock用来锁定版本信息的。一般团队开发,我们会把这个文件提交到仓库,避免出现不同同学安装不同的依赖。carthage update其实就是carthage build和carthage checkout的集合,因此会生成上述提到的两个文件夹。Build目录下放置编译好的默认动态库,checkouts默认放置检出的源码。
- 3.添加Framework到项目中
打开Xcode项目,选择Target->General选项卡,然后再底部找到Linked Frameworks and Libraries。打开项目根目录下Carthage/Build/iOS,找到你需要的Framework,然后把这几个库拖进来。这边我用Swift更新的时候死活更新下来,就用OC的两个库代替了,反正也就是对应的Alamofire和SnapKit这两个库


然后找到target->build phase选项卡,添加一个New Run Script Phase,然后添加新的脚本/usr/local/bin/catthage copy-frameworks。点击下面的Input Files,给对应的库添加。

这里在目录下创建了一个input.xcfilelist和output.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

本文对比分析了Carthage与Cocoapods在iOS项目中的应用,介绍了Carthage的去中心化管理、手动集成特性,以及如何在项目中添加Carthage生成的Framework。此外,还讲解了Carthage的安装、依赖管理和制作自己的Carthage库的流程。
705

被折叠的 条评论
为什么被折叠?



