使用Carthage在iOS上建立依赖关系

在本文中,我想分享我使用Carthage构建依赖项的经验。 首先,迦太基闪耀着简单。 通过在Cartfile添加适当的行并运行carthage update ,开始在Xcode项目中使用某些外部依赖关系非常简单。 但是众所周知,生活是残酷的,有时我们需要考虑更复杂的例子。

假设有一个iOS开发人员团队。 Tony,John和Keith正在使用约15种流行依赖项(例如Alamofire,Kingfisher,ReactiveCocoa等)运行iOS应用程序。

  • 不同的编译器 -有些库是用Swift编写的,这意味着每个不同的编译器运行时都与其他运行时不兼容。 如果那些开发人员使用不同版本的Xcode,这可能是一个巨大的问题。 他们每个人都需要构建自己的框架版本或使用相同版本的Xcode。
  • 清理构建时间 -这是最近的热门话题,有时我们需要关心构建时间,尤其是在CI上以及在分支之间切换时。 团队认为他们不想花很多时间(例如1个小时)等待发布,所以这个问题可能很关键。
  • 存储库大小 -一些开发人员更喜欢在存储库中包含已编译的框架。 团队正在使用免费的github计划,因此其最大存储库大小为1GB。 在回购中存储框架可能会导致其大小大幅增加,甚至达到5GB左右。 即使回购存储限制不成问题,克隆这样的存储库也将花费大量时间 。 这对于干净的构建时间可能会产生巨大的影响,尤其是在将CI与虚拟机一起使用时。
  • 更新框架 -在不进行额外工作的情况下,迦太基会在运行carthage update时重新编译所有框架,或者如果为单个依赖项而运行则仅会编译一个框架。 在项目开始时,我们经常这样做。 团队也在寻找解决方案以加快这一步。

没有免费的午餐……我同意,但是与此同时,我相信有时值得花一些时间来改善日常工具。 我花了很多时间来测试依赖项管理器,缓存其工件等。让我告诉您有关维护迦太基框架的三种流行解决方案。

在你开始之前

  • 如果您不熟悉迦太基,请先查看它的存储库。
  • 我不会考虑将迦太基框架直接存储在存储库中。

让故事开始……托尼是团队负责人,他决定使用迦太基作为依赖性管理器。 他在使用外部框架时为其他开发人员定义了一些规则:

  • 将Carthage / Build添加到.gitignore并在存储库中包括Carthage/Checkouts
  • 首次克隆存储库时,您需要运行carthage bootstrap (重建所有依赖项)。 CI需要为每个管道运行该程序,
  • 更新框架时,请仅更新一个框架,例如carthage update ReactiveSwift

这些规则很简单,但是它们的优缺点又如何呢?

优点:

  • 免费(每月费用0$
  • 仓库的规模永远不会急剧增加

缺点:

  • 非常长的整洁版本
  • 绝对不会重复使用预编译的框架
  • 存储库中的其他人的代码

让我们将此解决方案与可能出现的问题进行比较:

总结一下:这种方法的最大问题是时间 。 唯一完全解决的问题是存储库大小。 CI的构建时间将非常长,并且将随依赖项数量成比例地增加。 如您所见,还有很多地方需要改进。 让我们尝试一些不同的东西…

有一天,开发人员之一约翰(John)发现github允许在其LFS(大文件系统)中存储大文件。 他注意到,这可能是一个很好的机会,可以在git repo中开始包括预编译的框架,但仍要使其保持较小。 他对托尼的规则做了一些修改:

  • Carthage/Build Carthage/Checkouts 添加到.gitignore
  • 首次克隆存储库时-您无需运行carthage bootstrap (重建所有依赖项),但是您需要从LFS中提取框架,
  • 在更新框架时,请仅更新一个框架,例如carthage update ReactiveSwift ,这需要做一些额外的工作 -您需要存档这些框架,将它们压缩并上传到git-lfs(添加到.gitattributes ),
  • 所有团队成员必须具有相同的Swift编译器版本(Xcode版本)。

该解决方案要复杂得多,特别是由于压缩和上传框架需要执行额外的步骤。 有一篇很棒的文章对此进行了描述,并提供了一些简单的Makefile来自动执行此步骤。

优点:

  • 储存库大小仍然没有增长
  • 克隆和提取后,您就可以开始了

缺点:

  • 在大多数情况下不是免费的(在LFS上达到1GB后,每月费用为5$
  • 每个开发人员必须使用相同的Xcode版本
  • 没有加速框架更新的机制

让我们将此解决方案与本文开头定义的问题进行比较:

毕竟,我认为这看起来要好得多! 对于大多数团队而言,拥有快速清洁的构建比在开发人员之间使用不同Xcode的可能性更为重要。 他们仍然能够安装不同的版本,并且仅在特定项目之间切换。 我相信LFS每月5$不是什么大问题。 因此,这是一个更好(又困难)的解决方案,但是仍有一些改进的余地……

所以,是时候让基思露面了。 他赞赏其他开发人员的研究,但Keith非常关心团队合作。 他认为也许可以在不同的项目之间共享由不同版本的swift编译器编译的不同版本的预编译框架吗? 种类繁多,但是幸运的是有一个工具! 叫Rome 。 我强烈建议您阅读github上的文档。 通常,此工具使用Amazon S3 Bucket共享框架。 Keith再次更改了规则:

  • Carthage/Build Carthage/Checkouts 添加到.gitignore
  • 首次克隆存储库时,您无需运行carthage bootstrap (重建所有依赖项),但需要从Amazon S3下载它们,
  • 更新框架时,请仅更新一个框架版本,例如carthage update ReactiveSwift --no-build ,然后尝试从Amazon下载它,如果不存在,请构建并上传,
  • 您需要定义RepositoryMap ,它告诉罗马您使用的迦太基编译了哪些依赖项。

通过使用一些非常简单的帮助程序脚本,这些规则似乎几乎与“ Naive approach部分中的规则一样简单。 这个工具给我留下了深刻的印象,尤其是所需的设置工作量和给定收益之间的关系。 让我们看看此解决方案的优缺点:

优点:

  • 储存库大小仍然没有增长
  • 克隆并下载后,您就可以开始了
  • 在所有公司开发人员之间共享框架(非常简单的框架更新,因为有人可能已经为您编译了正确的版本)
  • 随意使用不同版本的Xcode
  • 由于使用RepositoryMap ,可以更好地了解依赖项
  • 能够计划在CI上构建依赖项,然后在本地使用它们的能力

缺点:

  • 不是免费的,但它仍然比LFS$0.023 / GB )便宜

并进行比较,得出明显的结果:

在我看来,这种解决方案可为您节省大量的依赖管理时间。 当然,有时您需要在计算机/ CI上进行构建,但是必须保证将重复使用此作业。

因此,您已经注意到,我认为罗马是目前最好的解决方案,并且我强烈建议您使用此方法,但故事表明,我们始终可以改进某些方面。 您应该尝试不同的方法,然后选择解决问题的方法。 我相信在阅读Tony,John和Keith的故事时,您不仅注意到了迦太基(罗马)的最好朋友,而且注意到了更多。 这与团队合作和改善团队工作流程有关。 这些家伙一直努力解决共同工作的问题(与CI作为虚拟的第四小组成员),最后其中一个找到了最适合他们需求的解决方案!

  • 迦太基github
  • Git LFS
  • 关于迦太基+ LFS的中篇文章
  • BFG-迁移到LFS的工具
  • 罗马github
  • AWS凭证

最初在 appunite.com上 发布