常见问题解答

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

什么是 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 万个源文件,而未更改文件的 build 大约需要 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 会生成确定性结果。这消除了增量构建和干净构建、笔记本电脑和 CI 系统等之间的偏差。
  • Bazel 可以使用同一工具从同一工作区构建不同的客户端和服务器应用。例如,您可以在单次提交中更改客户端/服务器协议,然后测试更新后的移动应用能否与更新后的服务器配合使用,使用同一工具构建二者,从而获得 Bazel 的上述所有优势。

我可以查看示例吗?

可以。查看简单示例或参阅 Bazel 源代码,查看更复杂的示例。

Bazel 最擅长什么?

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

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

在哪里可以运行 Bazel?

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

只要 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 不需要干净的构建就能确保正确性,因此在开始构建/测试运行之前,不应将 CI 系统配置为清理。

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

Bazel 未来有哪些功能?

请参阅我们的路线图

我可以将 Bazel 用于我的“INSERT LANGUAGE HERE”项目吗?

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

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

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

请参阅我们的贡献准则

为什么不是所有开发都是在公开的情况下完成的?

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

完成开源 Bazel 了吗?

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

  • 我们的许多单元测试和集成测试(这会使贡献补丁变得更容易)。
  • 完全集成 IDE。

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

Bazel 的哪些部分永远不会开源?

是的,部分代码库要么与 Google 专有的技术集成,要么我们一直寻找放弃的借口(或者将两者结合起来)。GitHub 上没有这些代码库部分,可能永远也不会有。

如何与 Google Ads 团队联系?

我们的联系方式为 bazel-think@googlegroups.com。

在哪里报告错误?

在 GitHub 上提交问题。

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

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

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

在第一个(Alpha 版)版本之前,Bazel 无法对外提供,因此 Chromium 和 Android 等开源项目无法使用它。此外,最初缺乏 Windows 支持是构建 Windows 应用(例如 Chrome)的问题。由于该项目日趋成熟且更加稳定,因此 Android 开源项目正在迁移到 Bazel。

“Bazel”一词是如何发音的?

与美国英语中的“basil”(草本)一样,“BAY-zel”。它与“hazel”押韵。IPA:/记播电各个名