依赖管理器:在Cocoapods和Carthage之间切换

最初 Andres 于2018年7月30日 发布在 可缩放路径 上。

如今,编写所有自己的代码的开发人员很少,而且有充分的理由。 当您找到写得很好,受良好支持的第三方库来帮助更快地构建产品时,为什么还要重新发明轮子呢? 实际上,我们只是写了一篇文章,描述了我们自己的评估第三方库的过程。

在您的项目中插入其他人的代码确实会引发一些问题,包括需要有效管理所有这些不同的库。 依赖管理器通常扮演的角色。

依赖项管理器只是一个工具,可以帮助您将外部库集成到项目中。 通常,它们包括一个列出哪些库和版本可用以及如何获取它们的列表。 一旦依赖性管理器了解了所有这些信息,它将负责获取正确的版本并将其集成到您的项目中(或让库准备在以后由您集成)。

在本文中,我将重点介绍在Apple环境中使用的依赖项管理器:Carthage,CocoaPods和Swift Package Manager。

这篇文章不是依赖管理器的初学者指南,而是交叉引用,因此开发人员可以轻松地学习在CocoaPods和Carthage之间进行切换。 例如,假设您与CocoaPods进行了广泛的合作,但是突然发现自己参与了一个使用Carthage的新项目。 您不需要学习什么是迦太基-您只需要学习如何执行以前在Cocoapods中但在Carthage上执行过的动作。 本文将促进这种日益普遍的过渡。 我还概述了较新的Swift Package Manager的介绍,以突出其当前的用例和弱点。

CocoaPods于2011年推出,是Cocoa和Cocoa Touch环境的第一个依赖项管理器。 由于它是用Ruby编写的,因此必须作为Gem分发。 因此,您将需要CocoaPods的Ruby语言的兼容版本。 在撰写本文时,cocoapods-core gem需要Ruby 2.0.0或更高版本(macOS 10.13.3随Ruby 2.3.3一起提供,因此这不应该成为问题)。

CocoaPods具有集中式方法。 这意味着CocoaPods具有一个存储库(位于Github上),该存储库将Pod的名称(库在CocoaPods上接收到的名称)映射到Pod的下载位置。 采用集中化方法的优点是您拥有一个可以在CocoaPods上存储所有可用库的元数据的地方。 反过来,这提供了一种搜索库的简单方法。 缺点是,如果该存储库发生故障,您将无法解决您的依赖项。

在迦太基中,当您运行carthage update ,程序将检查依赖关系,将其构建并保留,以供您抓取并将其集成到项目中。 CocoaPods不同,当您运行pod install ,它将下载库并创建一个新的.xcworkspace。 生成的.xcworkspace将在其中包含两个项目:您刚刚创建的项目和另一个称为“ pods”的项目。 从现在开始,您将必须使用此工作区来开发应用程序。 您可以查看下面的屏幕截图,以更清楚地了解这一点。

编译项目时,依赖项也会被编译。 CocoaPods仅通过运行pod install即可配置所有内容。 真好!

为了表明您要在项目中使用哪些库,您需要将它们添加到Podfile中。 这是一个ruby文件,您可以在其中指定要安装的Pod,版本和目标。 同样, pod install命令将生成一个Podfile.lock文件,该文件旨在跟踪您的库的安装版本。 这在概念上与Carthage的Cartfile.resolved文件相似。

她就是Podfile的样子:

 平台:ios,“ 9.0” 
disable_all_warnings!target'MyApp'做
pod'ObjectiveSugar','〜> 0.5'目标“ MyAppTests”做
继承! :search_paths
pod'OCMock','〜> 2.0.1'
结束
结束

如您所见,定义容器的语法如下:

  pod'PodName,'Version' 

迦太基和CocoaPods都使用语义版本控制,因此指定版本的方法是:

您还可以指定要使用的提交,标签或分支:

  pod'Alamofire',:git =>'https://github.com/Alamofire/Alamofire.git',:commit =>'0f506b1c45'pod'Alamofire',:git =>'https://github.com/ Alamofire / Alamofire.git',:tag =>'3.1.1'pod'Alamofire',:git =>'https://github.com/Alamofire/Alamofire.git',:branch =>'dev' 

如果您需要向项目中添加新的依赖项,只需将依赖项添加到Podfile中,然后运行pod install 。 这不会重新安装您的依赖项,而是将Podfile与Podfile.lock进行比较以识别新的依赖项,然后安装新的依赖项。 所有其他库保持不变。

现在,如果要更新所有依赖项,会发生什么。 运行pod install将无法工作,因为它将仅安装新的依赖项。 相反,您需要使用pod update (类似于carthage update ),此命令将更新podfile中列出的所有pod。 如果只想更新一个Pod,则可以将名称添加到命令中,并且仅此库将被更新: pod update name_of_pod (与carthage update name_of_pod相同)。

从一开始,迦太基就与可可豆大不相同。 它是用Swift而不是Ruby编写的。 而且,至关重要的是,它是分散的。 因此,没有可以像使用CocoaPods一样搜索图书馆的地方。 要找到您的依赖关系,您将不得不依赖Github或Google。 这种方法的优点是没有单点故障:在CocoaPods中,“库名称”和“库下载位置”之间没有转换。

迦太基将仅下载和构建您的库(使用xcodebuild)。 您将必须手动将每个这些库安装到项目中。 与Cocoapods相比,这是一个巨大的负面影响,在Cocoapods中,您只需运行命令,打开生成的xcworkspace,您就可以开始了。

在迦太基中最常见的命令是迦太基carthage update 。 这将把您的依赖项检出到Carthage / Checkouts文件夹中并建立依赖项。 如果您不carthage update迦太基并且carthage update办公桌前,想知道为什么carthage update花费的时间比pod install通常要长得多:这是因为第一个命令下载并生成所有内容,而第二个命令仅下载依赖项。

在迦太基,我们有一个Cartfile和一个Cartfile.private,而不是Podfile。 Cartfile列出了您要在应用程序中使用的所有依赖项。 指定依赖项的方式与CocoaPods相似,每个依赖项都声明为源(git,github或二进制)和版本要求。

版本要求的工作方式与CocoaPods相似。

Cartfile的外观如下:

  github“ realm / realm-cocoa”“ v3.3.0” github“ Alamofire / Alamofire”〜> 4.7github“ airbnb / lottie-ios”“ 2.1.4” 

如您所知,CocoaPods创建一个.xcworkspace,并将您的库集成到其中。 迦太基是不同的,在运行carthage update ,您将看到已构建的库,但是要由您来抓取并将它们集成到您的项目中。 编译的库将显示在carthage/build/文件夹中。 如果您想了解有关如何集成这些库的详细教程,没有比官方文档更好的地方了:向应用程序添加框架。

carthage update完成运行时,您将在目录中找到一个名为Cartfile.resolved的新文件。 该文件与Podfile.lock具有相同的功能,并列出了为每个依赖项构建的版本。 当您要构建与初始carthage update中生成的依赖项相同时,这非常有用。

到目前为止,我们仅讨论了carthage update 。 如果我们要运行一个已经在使用Carthage的项目,则不能调用此命令,我们需要一个命令来获取Cartfile.resolved检出并构建此处列出的指定依赖项和版本。 在这种情况下,我们需要使用carthage bootstrap

回顾一下, carthage update将获取Cartfile中指定的最新版本,而carthage bootstrap将使用Cartfile.resolved来解决依赖关系。

但是,如果要添加新的依赖关系,我们应该怎么做? 好吧,我们不能运行carthage update因为这可能会更新某些版本的依赖项。 我们也不能运行carthage bootstrap 。 该依赖关系从未得到解决,因此不在Cartfile.resolved中。 在这种情况下,我们需要运行carthage update name_of_dependency

让我们看一个例子:如果我们有以下Cartfile,而我们只想更新(或第一次安装)一个库:

  github“ realm / realm-cocoa”“ v3.3.0” github“ Alamofire / Alamofire”〜> 4.7github“ airbnb / lottie-ios”“ 2.1.4” 

我们将运行:

 迦太基更新Alamofire lottie-ios 

最后,让我们看一下加快速度! 当您运行carthage update您会注意到它可能需要foooooooror来完成。 这是因为Carthage将克隆该库,对其进行构建并将其准备好用作框架。 但是我们可以大大加快这一过程!

我创建了一个新项目,并将以下内容添加到我的Cartfile中:

  github“ Alamofire / Alamofire”〜> 4.7.2 

现在我们运行更新:

  $迦太基更新 
***获取Alamofire
***在“ 4.7.3”处签出Alamofire ***在/var/folders/zv/10lxs76s7sq28fjhjfslcj_00000gn/T/carthage-xcodebuild.Gxkmfn.log中可以找到xcodebuild输出***在Alamofire中构建方案“ Alamofire macOS” .xcworkspace *** Alamofire.xcworkspace中的构建方案“ Alamofire watchOS” *** Alamofire.xcworkspace中的构建方案“ Alamofire iOS” *** Alamofire.xcworkspace中构建方案“ Alamofire tvOS”

正如您在这里看到的那样,迦太基正在构建三种不同的模式(每个平台一个),但是由于我的应用程序仅适用于iOS,所以我正在浪费大量时间。 第一个优化是告诉Carthage仅针对我使用的平台进行更新:

  $迦太基更新-平台iOS 
***获取Alamofire
***在“ 4.7.3”签出Alamofire
*** xcodebuild输出可在/var/folders/zv/10lxs76s7sq28fjhjfslcj_00000gn/T/carthage-xcodebuild.eWEzEL.log中找到
*** Alamofire.xcworkspace中的构建方案“ Alamofire iOS”

现在速度更快了,但是迦太基仍在获取并重建一个已经存在的框架。

  $迦太基更新-平台iOS-缓存构建 
***获取Alamofire
***在“ 4.7.3”签出Alamofire
*** xcodebuild输出可以在/var/folders/zv/10lxs76s7sq28fjhjfslcj_00000gn/T/carthage-xcodebuild.OZTapd.log中找到
***找到Alamofire的有效缓存,跳过构建

代码--cache-builds告诉迦太基避免重新--cache-builds依赖关系(如果已构建)。 当然,我们可以对carthage bootstrap使用相同的标志,最终会得到:

  $ carthage bootstrap --platform iOS --cache-builds 
***在“ 4.7.3”签出Alamofire
*** xcodebuild输出可在/var/folders/zv/10lxs76s7sq28fjhjfslcj_00000gn/T/carthage-xcodebuild.a134Yj.log中找到
***找到Alamofire的有效缓存,跳过构建

这告诉迦太基“下载并构建已解析的库版本(Cartfile.resolved),并且仅针对iOS以前从未构建的库进行构建”。

Swift套件管理器(SPM)是在Swift 3.0发行版中引入的。 好消息是它是Swift附带的,因此已预装。 它旨在自动执行依赖项的下载,编译和链接过程。 我注意到的一个有趣的功能是SPM可以在Linux和macOS上运行。

它是分散式的(例如Carthage)和开源的(例如CocoaPods和Carthage)。

SPM是新的,因此,它仍然非常有限。 目前,它不支持iOS,watchOS或tvOS平台。 有一些变通办法可以使SPM在这些平台上工作,但是它们感觉“肮脏”,并且默认情况下不受支持。 我不鼓励您使用它们。 另一个缺点是SPM仅支持Swift。 如果您想使用用Objective C编写的任何很棒的库-很难-您将无法使用SPM做到这一点。

因此,如果不能在iOS,watchOS或tvOS上使用它,为什么要麻烦呢? 好吧,您可以将其用于不在这些平台上运行的任何类型的应用程序。 例如,作为Swift服务器端框架的Perfect,Vapor和Kitura使用SPM。

SPM的限制使其很难与CocoaPods或Carthage进行比较。 我建议您坐在这轮游戏中,静观其变,看看Apple在SPM的新版本中带来了什么!

而已! 让我给您一个方便的备忘单,无论您使用什么依赖项管理器,我都会将其汇总在一起以帮助您查找和运行命令。

您想和Andres合作吗? 与我们联系,我们将帮助您为下一个项目雇用优秀的开发人员。


要阅读可扩展路径团队的更多帖子,请访问我们的 博客