Bazel 和 Gradle 有什么区别?

What are the differences between Bazel and Gradle?

Google只是open-sourced its build tool Bazel. What are the differences between this tool and Gradle?它能做什么而 Gradle 不能,它在什么方面做得更好,在什么方面 Gradle 做得更好?

免责声明:我在 Bazel 工作,对 Gradle 不是很熟悉。然而,我的一位同事写了两个系统的比较,我将在这里解释一下:

Bazel 和 Gradle 强调构建体验的不同方面。在某种程度上,他们的优先级是不相容的——Gradle 对灵活性和非侵入性的渴望限制了它可以对构建结构施加的限制,而 Bazel 对可靠性和性能的渴望必然强制执行不可协商的限制。

Gradle 确实重视与 Bazel 相同的原则,即 Gradle 团队非常注重性能(增量构建、并行配置和执行、Gradle 守护进程),正确性(基于内容的“最新”检查)和可重复性(对声明语法、依赖版本控制、显式声明的依赖项的丰富支持)。 Bazel 尊重灵活项目布局的需求。

细微差别在于 Gradle 想要推广良好实践,而 Bazel 想要要求它。 Gradle 的目标是在 Ant 体验(自由定义您自己的项目结构但结果不一致)和 Maven 体验(强制最佳实践,没有满足不同项目需求的空间)之间的中间地带。 Bazel 认为,在不牺牲支持其强大工作流的强有力保证的情况下,灵活的项目支持是可能的。

这两种哲学都不“正确”——最适合项目的工具取决于该特定项目的价值观。

Gradle 概述

Gradle 是一个高度灵活的系统,使用户可以轻松构建完整、可靠的构建流程,同时对项目组织方式的限制最小。它通过提供强大的构建块(例如自动依赖跟踪和检索、紧密集成的插件支持)和通用的、图灵完备的脚本接口来实现这一点,该接口可以根据用户的需要组合这些块。

Gradle强调以下特点:

  • 从其他系统轻松迁移。 Gradle 轻松适应任何项目组织,轻松实现任意工作流结构。它本机理解 Ant 任务,并与 Maven 和 Ivy 存储库本机集成。
  • 高度可扩展的脚本模型。 用户通过编写 Groovy 脚本来实现所有构建逻辑。 “构建”只是一般任务的依赖顺序执行,这些任务本质上是开放式、可覆盖、可扩展的方法定义。
  • 丰富的依赖管理。 可以从外部代码存储库、本地文件系统和其他 Gradle 项目声明并自动暂存版本依赖。构建输出同样可以自动发布到存储库和其他位置。
  • 紧密集成的插件系统。 插件只是为促进所需工作流而组织的任务包。 Gradle 的许多 "core" 功能实际上是通过插件实现的(例如 Java、Android)。插件(自行决定)与构建脚本逻辑紧密交互。插件可以深入访问 Gradle 的核心数据结构。

Bazel 概览

Bazel 的发展源于可靠高效地构建内部 Google 项目的需要。由于 Google 的开发环境异常庞大和复杂,Bazel 为其构建的完整性提供异常强大的保证,并在实现它们时提供异常低的性能开销。

这为围绕可复制构建构建的强大开发工作流程提供了基础,其中“构建”成为一个抽象实体,可以引用、重复、传递给不同的机器,并传递给任意程序和服务,以便每个已知实例完全相同。

Bazel 强调以下特点:

  • 正确性。 Bazel 构建旨在始终产生正确的输出,期间。如果两个用户在不同机器上使用相同的 Bazel 标志在相同的提交中调用相同的构建,他们将看到相同的结果。增量构建与干净构建一样可靠正确,使后者基本上不必要。
  • 性能。 构建旨在在给定可用资源的情况下尽可能快地执行。任务在其依赖链允许的范围内可并行化。永远不会执行不必​​要的工作(即总是跳过“最新”任务)。工作自然可以外包给远程执行者以克服本地机器限制。
  • 可再现性。构建的任何实例都可以在任何环境中忠实地再现。例如,如果错误报告说软件 Y 的版本 X 在生产环境 Z 中失败,开发人员可以在自己的机器上忠实地重新创建它,并确信他们正在调试相同的东西。

由于文章链接容易失效,这里是the Gradle Team's views on Bazel的总结(大部分直接摘自2015年3月发表的文章):

它旨在解决 Google 独有的问题;庞大的单体代码库(数亿行代码)。

Bazel 当前提供的并行化优势将与 "our upcoming new configuration and component model" 相匹配(请记住此处的文章日期)。

Bazel 没有使开发人员易于使用的高级声明式构建语言。在 Google,这可以通过拥有构建工具的专业服务团队进行补偿。

Bazel 不是为可扩展性而构建的(尽管 Bazel 开发团队已经反驳了这一点,并保证他们正在致力于可扩展性)。

围绕所有传递依赖项都存储在一个大仓库中的想法优化了速度;所有库和工具都被签入这个中央存储库。大多数企业有更多的分布式依赖管理需求。

Bazel 仅适用于 *nix,它在 Windows 上不 运行。这消除了大量潜在的企业。

没有插件生态系统。

Gradle 主要用于 JVM 生态系统(Java、Ggroovy、Scala、Kotlin ...)。如果你的项目在这方面,而且你必须要问这个问题,Gradle 或 Maven 会是更好的选择。要对 Gradle 构建进行故障排除,您将仅与 Java 和 JVM 生态系统争论不休。

Bazel 的核心是能够检测增量更改(以及分布式构建缓存)并允许您做出反应,应用 plugins/rules 来实现增量构建。要设置和维护它需要一些 CPP 知识,Java 和 Python(Skylark) 以及系统管理员的知识。同样,如果您不得不问这个问题,我认为 Gradle 或 Maven 是一项更便宜的投资。使用 Bazel,您可以构建任何语言,以任何您定义的方式,更强大,但需要付出代价。