本节介绍 Gradle 构建缓存的不同用例,从仅限本地的开发到跨大型团队缓存任务输出。

使用本地缓存加速开发人员构建

即使仅由单个开发人员使用,构建缓存也非常有用。Gradle 的增量构建功能有助于避免已经完成的工作,但一旦重新执行任务,任何先前的结果都会被遗忘。当您在分支之间来回切换时,本地结果会一遍又一遍地重建,即使您正在构建之前已经构建过的内容。构建缓存会记住先前的构建结果,并极大地减少了在本地已经构建过内容时重新构建的需要。这也可以扩展到重建不同的提交,例如在运行git bisect时。

当处理具有多个变体的项目时,本地缓存也很有用,例如 Android 项目。每个变体都与许多任务相关联,其中一些任务变体维度,尽管名称不同,但最终可能会产生相同的输出。启用本地缓存后,将在适用时自动在任务变体之间重用。

在 CI 构建之间共享结果

构建缓存不仅仅可以回溯时间:它还可以弥合计算机之间的物理距离,允许在一台机器上生成的结果被另一台机器重用。在团队中引入构建缓存的典型第一步是仅为作为持续集成一部分运行的构建启用它。使用共享的 HTTP 构建缓存后端(例如 Develocity 提供的构建缓存后端)可以显著减少 CI 代理需要执行的工作量。这转化为开发人员更快的反馈,以及在 CI 资源上花费更少的资金。更快的构建也意味着每个构建中包含的提交更少,这使得调试问题更加高效。

从 CI 上的构建缓存开始是一个好的第一步,因为 CI 代理上的环境通常比开发人员机器上的环境更稳定和可预测。这有助于识别可能影响可缓存性的构建中的任何潜在问题。

如果您受到有关交付给客户的工件的审计要求的约束,您可能需要为某些构建禁用构建缓存。Develocity 可以帮助您满足这些要求,同时仍然为所有构建使用构建缓存。它允许您轻松地通过构建扫描找出哪个构建产生了来自构建缓存的工件。

from cache origin

通过重用 CI 结果加速开发人员构建

当多个开发人员在同一个项目上工作时,他们不仅需要构建自己的更改:每当他们从版本控制中拉取时,他们最终也需要构建彼此的更改。每当开发人员正在处理与拉取的更改无关的事情时,他们可以安全地重用已经在 CI 上生成的输出。例如,您正在处理模块“A”,并且您拉取了对模块“B”的一些更改(该模块不依赖于您的模块)。如果这些更改已经在 CI 中构建,您可以从缓存中下载模块“B”的任务输出,而不是在本地生成它们。此功能的典型用例是开发人员开始工作时,从版本控制中拉取所有更改,然后运行他们的第一个构建。

更改也不需要完全独立;我们将在关于 不同形式的规范化 的部分中查看在存在依赖关系时重用结果的策略。

将远程结果与本地缓存结合

您可以同时使用本地缓存和远程缓存来实现复合效果。从充满 CI 的远程缓存中加载结果有助于避免由于其他开发人员的更改而需要的工作,而本地缓存可以加速分支切换和执行 git bisect。在 CI 机器上,本地缓存可以充当远程缓存的镜像,从而显著减少网络使用量。

在开发人员之间共享结果

允许开发人员将他们的结果上传到共享缓存是可能的,但不建议这样做。开发人员可以在任务执行期间更改任务输入或输出。他们可能会无意中这样做,并且没有注意到,例如在构建运行时在他们的 IDE 中进行更改。目前,Gradle 没有很好的方法来防御这些更改,并且将在任务完成后简单地缓存输出目录中的内容。这再次会导致损坏的结果被上传到共享缓存。当 Gradle 添加了必要的保护措施以防止无意修改任务输入和输出时,此建议可能会更改。

如果您想从增量构建(即非清理构建)中共享任务输出,您必须确保所有可缓存的任务都已正确配置并实现,以处理陈旧的输出。例如,有些注解处理器不会清理对应类/资源目录中的陈旧文件。缓存是一个很好的强制功能来解决这些问题,这将使您的增量构建更加可靠。同时,在您确信增量构建行为完美无缺之前,只使用清理构建将内容上传到缓存。