常见问题解答

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

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 的前 Google 员工以及 Facebook 创建和开发。它们以 Bazel 为模型,但功能集不同,因此对我们来说不是可行的替代方案。

Bazel 的由来

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

您是否将内部工具重写为开源工具?它是分支吗?

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

Google 为什么要构建 Bazel?

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

Bazel 是否需要构建集群?

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

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

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

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

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

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

您为什么要开放 Bazel?

构建软件应该是一件轻松愉快的事情。缓慢且不可预测的构建会使编程失去乐趣。

我为什么要使用 Bazel?

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

我可以查看示例吗?

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

Bazel 最擅长什么?

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

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

我可以在哪里运行 Bazel?

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

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

我不应该将 Bazel 用于什么?

  • Bazel 会尝试智能地进行缓存。这意味着,它不适合运行输出不应缓存的构建操作。例如,不应从 Bazel 运行以下步骤:
    • 从互联网提取数据的编译步骤。
    • 连接到网站的 QA 实例的测试步骤。
    • 更改网站的云配置的部署步骤。
  • 如果您的构建包含几个较长的顺序步骤,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 会自动使我的构建可重现吗?

对于 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 中期待哪些未来的功能?

请参阅我们的路线图

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

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

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

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

请参阅我们的贡献指南

为什么不公开进行所有开发?

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

您是否已完成 Bazel 的开源?

Bazel 的开源工作正在进行中。具体而言,我们仍在努力开源:

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

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

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

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

如何与团队联系?

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

在哪里报告 bug?

在 GitHub 上提出问题

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

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

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

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

“Bazel”怎么发音?

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