常见问题解答

报告问题 查看源代码

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

什么是 Bazel?

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

Bazel 有何特别之处?

Bazel 的设计宗旨符合 Google 的软件开发方式。它具有以下功能:

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

Google 为什么不使用...?

  • Make、Ninja:这些工具可以非常精确地控制调用哪些命令来构建文件,但正确的规则由用户决定。
    • 用户在更高级别与 Bazel 进行交互。例如,Bazel 内置了针对“Java 测试”“C++ 二进制文件”以及“目标平台”和“主机平台”等概念的规则。这些规则都经过实践检验,是万无一失的。
  • Ant 和 Maven:Ant 和 Maven 主要面向 Java,而 Bazel 可处理多种语言。Bazel 鼓励将代码库细分为可重复使用的较小单元,并且只能重新构建需要重新构建的单元。处理较大的代码库时,这样可以加快开发速度。
  • Gradle:Bazel 配置文件比 Gradle 的配置文件要结构清晰得多,这让 Bazel 能够准确了解每个操作的用途。这样可以提高并行处理和可重现性。
  • Pants, Buck:这两种工具分别由 Twitter 和 Foursquare 和 Facebook 的前 Google 员工开发和开发。它们是按照 Bazel 构建的,但它们的功能集有所不同,因此并不是可行的替代方案。

Bazel 来自哪里?

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

您是否将内部工具重写为开源工具?这是一把叉子吗?

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

Google 为什么要构建 Bazel?

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

Bazel 需要构建集群吗?

默认情况下,Bazel 会在本地运行构建操作。但是,Bazel 也可以连接到构建集群,从而更快速地进行构建和测试。如需了解详情,请参阅我们关于远程执行和缓存以及远程缓存的文档。

Google 的开发流程是怎样运作的?

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

  • 我们的所有服务器代码都在一个庞大的版本控制系统中。
  • 每个人都使用 Bazel 构建软件。
  • 不同的团队拥有源代码树的不同部分,并使他们的组件可作为 BUILD 目标使用。
  • 分支主要用于管理版本,因此每个人都会在主要修订阶段开发软件。

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

如需了解 Google 开发流程的更多背景信息,请参阅 eng 工具博客

你为什么打开 Bazel?

构建软件应该既有趣又简单。缓慢且不可预测的构建会让编程乐趣无穷。

为什么要使用 Bazel?

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

我可以查看示例吗?

有。查看简单示例或查看 Bazel 源代码,了解更复杂的示例。

Bazel 最擅长什么?

Bazel 擅长构建和测试具有以下属性的项目:

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

可以在哪里运行 Bazel?

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

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

我不应将 Bazel 用于哪些用途?

  • Bazel 会尽量精巧地处理缓存。这意味着它不适合运行输出不应缓存的构建操作。例如,不应从 Bazel 运行以下命令:
    • 从互联网提取数据的编译步骤。
    • 连接到您网站的质量检查实例的测试步骤。
    • 用于更改您网站的云配置的部署步骤。
  • 如果您的构建包含几个冗长的连续步骤,则 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 内部,我们会将工具纳入源代码控制机制,以确保可重现性。通过这种方式,我们可以审查工具的更改(“将 GCC 升级到 4.6.1”),其机制与对基础库的更改相同(“修复 OpenSSL 中的边界检查”)。

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

借助 Bazel,您可以使用 C/C++ 构建独立的静态链接二进制文件,以及为 Java 构建独立的 jar 文件。它们在普通 UNIX 系统上运行时几乎没有依赖项,因此应该很容易安装在 Docker 容器内。

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

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

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

Bazel 是否能让我的构建自动重现?

对于 Java 和 C++ 二进制文件,是的(假设您不更改工具链)。如果您的构建步骤涉及自定义配方(例如,通过规则中的 Shell 脚本执行二进制文件),则需要特别注意:

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

您是否有二进制版本?

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

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

如需了解 IntelliJ,请查看使用 Bazel 插件的 IntelliJ

对于 XCode,请查看 Tulsi

对于 Eclipse,请查看 E4B 插件

对于其他 IDE,请查看相关博文,了解这些插件的工作原理。

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

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

如需详细了解退出代码,请参阅用户手册

我们未来会在 Bazel 中有哪些功能?

请参阅我们的路线图

我可以将 Bazel 用于我的“在此处插入语言”项目吗?

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

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

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

请参阅我们的贡献准则

为什么所有开发工作都不是在开放环境中完成的?

我们仍然需要经常重构 Bazel 中的公开代码和内部扩展程序之间的接口。这使得在开放环境中进行大量开发很难。

您完成开源 Bazel 了吗?

开源 Bazel 仍在开发中。具体而言,我们仍在努力开源化:

  • 我们的许多单元测试和集成测试(这应该会使贡献补丁变得更加简单)。
  • 全面集成 IDE。

除了代码之外,我们希望最终在 Bazel 社区的参与下,公开进行所有代码审核、bug 跟踪和设计决策。我们还没有进行这些操作,因此一些更改只会出现在 Bazel 代码库中,并且没有明确说明。尽管缺乏透明度,我们也希望为外部开发者提供支持并开展协作。因此,尽管部分开发工作仍在 Google 内部开展,但我们仍会公开这些代码。在过渡到开放模式的过程中,如有任何不清楚或不合理的问题,请告知我们。

Bazel 中有些部分永远不会开源吗?

是的,有些代码库要么集成了 Google 专有技术,要么是我们一直在寻找消除这些代码库的理由(或者是将二者相结合的某种方法)。代码库的这些部分在 GitHub 上不可用,而且可能永远也不会提供。

如何与小组联系?

我们的邮箱是 bazel-discuss@googlegroups.com。

在哪里报告错误?

在 GitHub 上提交问题。

代码库中的“Blaze”一词怎么办?

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

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

在首个(Alpha 版)版本之前,Bazel 对外不可用,因此 Chromium 和 Android 等开源项目无法使用 Bazel。此外,最初对 Windows 的支持是构建 Windows 应用(例如 Chrome)时的一个问题。由于 Android 开源项目已经成熟并且更加稳定,因此正在迁移到 Bazel。

“Bazel”怎么说?

与美式英语中的“basil”(香草)一样:“BAY-zel”。它与“hazel”押韵。IPA:/品种中文