常见问题解答

如果您有疑问或需要支持,请参阅获取帮助

什么是 Bazel?

Bazel 是一款可自动执行软件构建和测试的工具。支持的 build 任务包括运行编译器和链接器以生成可执行程序和库,以及为 Android、iOS 和其他目标环境组装可部署的软件包。Bazel 与 Make、Ant、Gradle、Buck、Pants 和 Maven 等其他工具类似。

Bazel 有什么特别之处?

Bazel 的设计旨在适应 Google 的软件开发方式。它具有以下功能:

  • 多语言支持:Bazel 支持多种语言,并且可以扩展以支持任意编程语言。
  • 高级别 build 语言:项目以 BUILD 语言描述,这是一种简洁的文本格式,可将项目描述为一组相互关联的小型库、二进制文件和测试。相比之下,使用 Make 等工具时,您必须描述各个文件和编译器调用。
  • 多平台支持:可以使用相同的工具和相同的 BUILD 文件来构建适用于不同架构甚至不同平台的软件。在 Google,我们使用 Bazel 构建各种内容,从在数据中心系统上运行的服务器应用到在手机上运行的客户端应用,无所不包。
  • 可重现性:在 BUILD 文件中,每个库、测试和二进制文件都必须完整指定其直接依赖项。Bazel 会使用此依赖项信息来了解在您更改源文件时必须重新构建的内容,以及哪些任务可以并行运行。这意味着所有 build 都是增量 build,并且始终会生成相同的结果。
  • 可扩缩:Bazel 可以处理大型 build;在 Google,服务器二进制文件通常包含 10 万个源文件,而未更改任何文件的 build 大约需要 200 毫秒。

Google 为什么不使用…?

  • Make、Ninja:这些工具可非常精确地控制调用哪些命令来构建文件,但用户必须自行编写正确的规则。
    • 用户在更高层面上与 Bazel 互动。例如,Bazel 具有“Java 测试”“C++ 二进制文件”的内置规则,以及“目标平台”和“宿主平台”等概念。这些规则经过实战检验,可确保万无一失。
  • Ant 和 Maven:Ant 和 Maven 主要面向 Java,而 Bazel 可处理多种语言。Bazel 鼓励将代码库细分为更小的可重用单元,并且可以仅重新构建需要重新构建的单元。这样可以加快处理大型代码库时的开发速度。
  • Gradle:Bazel 配置文件比 Gradle 的结构化程度高得多,可让 Bazel 准确了解每项操作的作用。这样可以提高并行性并改善可重现性。
  • Pants、Buck:这两款工具分别由 Twitter 和 Foursquare 的前 Google 员工以及 Facebook 创建和开发。它们以 Bazel 为模型,但功能集不同,因此对我们来说不是可行的替代方案。

Bazel 是从哪里来的?

Bazel 是 Google 用于在内部构建其服务器软件的工具的一种变体。现在,它还可用于构建其他软件,例如连接到我们服务器的移动应用(iOS、Android)。

您是否将内部工具重写为开源工具?是 fork 吗?

Bazel 与内部工具共享大部分代码,其规则每天用于数百万次 build。

Google 为什么要构建 Bazel?

很久以前,Google 使用大型生成的 Makefile 构建其软件。这导致构建速度缓慢且不可靠,开始影响开发者的工作效率和公司的敏捷性。Bazel 是一种解决这些问题的方法。

Bazel 是否需要构建集群?

默认情况下,Bazel 会在本地运行构建操作。不过,Bazel 也可以连接到构建集群,以实现更快的构建和测试。如需了解详情,请参阅有关远程执行和缓存以及远程缓存的文档。

Google 的开发流程是怎样的?

对于服务器代码库,我们使用以下开发工作流:

  • 我们所有的服务器代码都位于一个巨大的版本控制系统中。
  • 每个人都使用 Bazel 构建自己的软件。
  • 不同的团队负责源代码树的不同部分,并将其组件作为 BUILD 目标提供。
  • 分支主要用于管理发布版本,因此每个人都在头部修订版本中开发自己的软件。

Bazel 是这一理念的基石:由于 Bazel 要求完全指定所有依赖项,因此我们可以预测哪些程序和测试会受到更改的影响,并在提交之前对其进行检查。

如需详细了解 Google 的开发流程,请参阅 engtools 博客

您为什么开放 Bazel?

构建软件应该既有趣又简单。缓慢且不可预测的 build 会让编程变得枯燥乏味。

为什么要使用 Bazel?

  • Bazel 可能会缩短 build 时间,因为它只会重新编译需要重新编译的文件。同样,它也可以跳过重新运行已知未更改的测试。
  • Bazel 会生成确定性结果。这样可以消除增量 build 和干净 build、笔记本电脑和 CI 系统等之间的偏差。
  • Bazel 可以使用同一工具从同一工作区构建不同的客户端和服务器应用。例如,您可以在一次提交中更改客户端或服务器协议,并测试更新后的移动应用是否能与更新后的服务器搭配使用,同时使用同一工具构建两者,从而获得 Bazel 的所有上述优势。

我可以查看示例吗?

可以;请参阅简单示例,或阅读 Bazel 源代码以了解更复杂的示例。

Bazel 最擅长什么?

Bazel 在构建和测试具有以下属性的项目方面表现出色:

  • 包含大型代码库的项目
  • 使用(多种)编译型语言编写的项目
  • 部署在多个平台上的项目
  • 具有广泛测试的项目

我可以在哪些平台上运行 Bazel?

Bazel 可在 Linux、macOS (OS X) 和 Windows 上运行。

只要平台有 JDK,移植到其他 UNIX 平台应该相对容易。

我不应将 Bazel 用于哪些方面?

  • Bazel 会尽可能智能地进行缓存。这意味着,它不适合运行不应缓存输出的 build 操作。例如,以下步骤不应通过 Bazel 运行:
    • 一种从互联网提取数据的编译步骤。
    • 连接到网站的 QA 实例的测试步骤。
    • 一种会更改网站云配置的部署步骤。
  • 如果您的 build 包含几个较长的连续步骤,Bazel 可能无法提供太多帮助。通过将长步骤分解为 Bazel 可以并行运行的较小离散目标,您可以获得更快的速度。

Bazel 的功能集有多稳定?

核心功能(C++、Java 和 shell 规则)在 Google 内部得到广泛使用,因此经过了全面测试,并且变动很小。同样,我们每天都会针对数十万个目标测试新版 Bazel,以发现回归问题,并且每个月都会多次发布新版本。

简而言之,除了标记为实验性的功能之外,Bazel 应该可以正常运行。 对非实验性规则的更改将向后兼容。如需查看更详细的功能支持状态列表,请参阅我们的支持文档

作为二进制文件的 Bazel 有多稳定?

在 Google 内部,我们确保 Bazel 崩溃的情况非常少见。我们的开源代码库也应如此。

如何开始使用 Bazel?

请参阅使用入门

Docker 不是可以解决重现性问题吗?

借助 Docker,您可以轻松创建具有固定操作系统版本(例如 Ubuntu 12.04、Fedora 21)的沙盒。这解决了系统环境的可重现性问题,即“我需要哪个版本的 /usr/bin/c++?”

Docker 无法解决源代码更改带来的可重现性问题。在 Docker 容器中使用编写不完善的 Makefile 运行 Make 仍可能会产生不可预测的结果。

在 Google 内部,我们会将工具签入源代码控制系统,以实现可重现性。这样一来,我们就可以使用与基础库更改(例如“修复 OpenSSL 中的边界检查”)相同的机制来审核工具更改(例如“将 GCC 升级到 4.6.1”)。

我可以构建二进制文件以部署到 Docker 上吗?

借助 Bazel,您可以在 C/C++ 中构建独立的静态链接二进制文件,并为 Java 构建自包含的 JAR 文件。这些工具在常规 UNIX 系统上运行时几乎没有依赖项,因此应该很容易在 Docker 容器内安装。

Bazel 具有用于构建更复杂程序的惯例,例如使用一组数据文件或将另一个程序作为子进程运行的 Java 程序。可以将此类环境打包为独立归档,以便部署在不同的系统上,包括 Docker 映像。

我可以使用 Bazel 构建 Docker 映像吗?

可以,您可以使用我们的 Docker 规则来构建可重现的 Docker 映像。

Bazel 会自动使我的 build 可重现吗?

对于 Java 和 C++ 二进制文件,答案是肯定的,前提是您不更改工具链。如果您的构建步骤涉及自定义配方(例如,通过规则内的 shell 脚本执行二进制文件),则需要格外注意:

  • 请勿使用未声明的依赖项。沙盒化执行(–spawn_strategy=sandboxed,仅限 Linux)有助于查找未声明的依赖项。
  • 避免在生成的文件中存储时间戳和用户 ID。ZIP 文件和其他归档文件尤其容易出现此问题。
  • 避免连接到网络。沙盒执行也能在这方面提供帮助。
  • 避免使用随机数的进程,尤其是在许多编程语言中,字典遍历是随机的。

您是否有二进制版本?

可以,您可以找到最新的发布二进制文件,并查看我们的发布政策

我使用 Eclipse/IntelliJ/XCode。Bazel 如何与 IDE 交互操作?

对于 IntelliJ,请查看 IntelliJ with Bazel 插件

对于 XCode,请查看 Tulsi

对于 Eclipse,请查看 E4B 插件

对于其他 IDE,请参阅有关这些插件如何运作的博文

我使用 Jenkins/CircleCI/TravisCI。Bazel 如何与 CI 系统互操作?

如果 build 或测试调用失败,Bazel 会返回非零退出代码,这应该足以满足基本的 CI 集成需求。由于 Bazel 不需要干净的 build 来确保正确性,因此不应将 CI 系统配置为在开始 build 或测试运行之前进行清理。

有关退出代码的更多详细信息,请参阅用户手册

Bazel 未来会推出哪些功能?

请参阅我们的路线图

我可以在 INSERT LANGUAGE HERE 项目中使用 Bazel 吗?

Bazel 具有可扩展性。任何人都可以添加对新语言的支持。支持多种语言:如需查看建议列表,请参阅构建百科全书;如需查看更全面的列表,请访问 awesomebazel.com

如果您想开发扩展程序或了解扩展程序的工作原理,请参阅有关扩展 Bazel 的文档。

我可以为 Bazel 代码库做贡献吗?

请参阅我们的贡献指南

为什么不公开完成所有开发工作?

我们仍然必须经常重构 Bazel 中的公共代码与内部扩展程序之间的接口。这使得在公开场合进行大量开发工作变得困难。

您是否已完成 Bazel 的开源?

Bazel 开源工作仍在进行中。具体而言,我们仍在努力实现以下开源项目:

  • 许多单元测试和集成测试(应该可以更轻松地贡献补丁)。
  • 完全 IDE 集成。

除了代码之外,我们还希望最终让所有代码审核、bug 跟踪和设计决策都公开进行,并让 Bazel 社区参与其中。我们尚未完成此项工作,因此一些更改会直接出现在 Bazel 代码库中,而没有明确的说明。尽管缺乏透明度,我们仍希望支持外部开发者并开展协作。因此,我们决定开放代码,即使部分开发工作仍在 Google 内部进行。在向开放模式过渡期间,如果您发现任何不明确或不合理之处,请告诉我们。

Bazel 是否有永远不会开源的部分?

是的,部分代码库要么与 Google 的特定技术集成,要么我们一直在寻找借口来摆脱(或两者兼而有之)。代码库的这些部分在 GitHub 上不可用,并且可能永远不会可用。

如何与该团队联系?

您可以通过 bazel-discuss@googlegroups.com 与我们联系。

在哪里报告错误?

在 GitHub 上提交问题。

代码库中的“Blaze”一词是什么意思?

这是该工具的内部名称。请将 Blaze 称为 Bazel。

为什么其他 Google 项目(Android、Chrome)使用其他 build 工具?

在第一个(Alpha 版)发布之前,Bazel 无法在外部使用,因此 Chromium 和 Android 等开源项目无法使用它。此外,最初缺乏 Windows 支持也给构建 Windows 应用(例如 Chrome)带来了问题。随着项目日趋成熟和稳定,Android 开源项目正在迁移到 Bazel。

“Bazel”怎么发音?

与美国英语中的“basil”(罗勒)发音相同:“BAY-zel”。与“hazel”押韵。IPA:/ˈbeɪzəl/