常见问题解答

报告问题 查看源代码 每夜 build · 8.0 · 7.4 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

Bazel 是什么?

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

Bazel 有什么特别之处?

Bazel 的设计符合 Google 的软件开发方式。它具有以下特点:

  • 多语言支持:Bazel 支持多种语言,并且可以扩展为支持任意编程语言。
  • 高级构建语言:项目使用 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 以及 Facebook 的 Google 前员工创建和开发。它们是仿照 Bazel 构建的,但功能集不同,因此不适合用作替代方案。

Bazel 的起源是什么?

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

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

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

Google 为什么构建 Bazel?

很久以前,Google 使用生成的大型 Makefile 构建软件。这导致构建速度缓慢且不可靠,进而影响了开发者的生产力和公司敏捷性。Bazel 就是用来解决这些问题的。

Bazel 是否需要构建集群?

Bazel 默认在本地运行构建操作。不过,Bazel 还可以连接到构建集群,以加快构建和测试速度。如需了解详情,请参阅我们关于远程执行和缓存以及远程缓存的文档。

Google 开发流程是如何运作的?

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

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

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

如需详细了解 Google 的开发流程,请访问工程工具博客

为什么要开源 Bazel?

构建软件应该是一件简单而有趣的事。构建速度缓慢且不可预测会让编程变得无趣。

为什么要使用 Bazel?

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

我可以看到示例吗?

可以;如需查看更复杂的示例,请参阅简单示例或阅读 Bazel 源代码

Bazel 最擅长做什么?

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

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

在哪里可以运行 Bazel?

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

只要平台支持 JDK,便应能相对轻松地移植到其他 UNIX 平台。

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

  • Bazel 会尝试智能地进行缓存。这意味着,对于不应缓存输出的运行 build 操作而言,这种方法并不适用。例如,不应通过 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 内部,我们会将工具签入源代码控制系统,以实现可重现性。这样,我们就可以使用与对基础库(“修复 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 系统互操作?

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

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

Bazel 未来会推出哪些功能?

请参阅我们的路线图

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

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

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

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

请参阅我们的贡献指南

为什么并非所有开发工作都是公开进行的?

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

您是否已将 Bazel 开源?

我们正在努力开源 Bazel。具体而言,我们仍在努力开源以下项目:

  • 我们的许多单元测试和集成测试(这应该有助于更轻松地贡献补丁)。
  • 完整的 IDE 集成。

除了代码之外,我们最终希望所有代码审核、 bug 跟踪和设计决策都能公开进行,并由 Bazel 社区参与。我们尚未达到这一目标,因此某些更改只会显示在 Bazel 仓库中,而没有明确说明。尽管如此,我们仍希望支持外部开发者并与他们合作。因此,我们将开源该代码,即使部分开发工作仍在 Google 内部进行也是如此。在我们过渡到开放式模型的过程中,如果您发现任何不明确或不合理的情况,请告诉我们。

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

是的,部分代码库要么与 Google 专用技术集成,要么我们一直在寻找机会将其移除(或者两者兼有)。代码库的这些部分无法在 GitHub 上找到,而且可能永远不会在 GitHub 上提供。

如何与该团队联系?

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

在哪里报告错误?

在 GitHub 上提交问题。

代码库中出现“Blaze”一词是怎么回事?

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

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

在第一个(Alpha)版本发布之前,Bazel 不对外提供,因此 Chromium 和 Android 等开源项目无法使用它。此外,最初缺少 Windows 支持对构建 Windows 应用(例如 Chrome)造成了影响。由于该项目已趋于成熟且变得更加稳定,Android 开源项目正在迁移到 Bazel。

“Bazel”怎么读?

与美式英语中的“basil”(香草)发音相同:“BAY-zel”。与“hazel”押韵。国际音标:/ˈbeɪzˌəl/