Google软件构建工具Bazel FAQ

本文是我的翻译,原文在这里。欢迎转载,转载请注名本文作者和原始链接
注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用方法介绍系列

Bazel是什么?

Bazel是一个构建工具,即一个可以运行编译和测试来组装软件的工具,跟Make、Ant、Gradle、Buck、Pants和Maven一样。

Bazel有什么特殊之处

Bazel是设计用来配合Google的软件开发模式。有以下几个特点:

  • 多语言支持:Bazel支持Java,Objective-C和C++,可以扩展来支持任意的编程语言
  • 高级别的构建语言:工程是通过BUILD语言来描述的。BUILD语言以简洁的文本格式,描述了由多个小的互相关联的库、二进制程序和测试程序来组成的一个项目。而与之相比,Make这类的工具需要描述各个单独的文件和编译的命令
  • 多平台支持:同一套工具和同样的BUILD文件可以用来构建不同架构和不同平台的软件。在Google,我们使用Bazel来构建在我们数据中心系统中运行的服务器端程序和在手机上运行的客户端应用程序。
  • 重现性[Reproducibility]:在BUILD文件中,每个库,测试程序,二进制文件必须明确完整地指定直接依赖。当修改源代码文件后,Bazel使用这个依赖信息就可以知道哪些必须重新构建,哪些任务可以并行执行。这意味者所有的构建都是增量形式的并能够每次都生成相同的结果。
  • 伸缩性[Scalability]:Bazel可以处理巨大的构建;在Google,一个服务器端程序超过100k的源码是常有的事情,如果没有文件被改动,构建过程需要大约200ms

为什么Google不使用...?

  • Make,Ninja: 通过这些工具都能够控制执行哪些命令来构建文件,但是需要用户书写正确的规则。

    用户跟Bazel在更高级别上交互。例如,它有内置的"Java test", "C++ binary"的规则[rule],有例如“目标平台”[target platform],“主机平台"[host platform]这种标记。这些规则都经历了充分的测试,是不会出错的。

  • Ant和Maven:Ant和Maven主要是面向Java,而Bazel可以处理多种语言。Bazel鼓励把代码库的内容划分成小的,可复用的单元,并且只重新构建需要重新构建的文件。这会提高在庞大的代码库上开发的速度。
  • Gradle: Bazel 配置文件比Gradle的要更加结构化,让Bazel能够准确理解每个行为的所作所为。使得能够有更多的并发和更好的可重现性
  • Pants, Buck: 这两个工具都是前Google员工在Twitter和Foursquare创造并开发的。他们都是在模仿Bazel,但是他们的特性跟Bazel是不同的,所以不会是Bazel的替代品

Bazel的起源是什么?

Bazel是Google内部用来构建自己的服务器端软件的工具。它已经被扩展成也可以构建连接到服务器端的客户端软件(iOS, Android)。

Bazel是内部工具的重写,然后开源?还是说它是一个fork?

Bazel和内部工具的大部分代码是一样的,它的规则每天被使用无数次。

为什么Google创建Bazel?

很久以前,Google使用大的,生成的Makefile来构建软件。这导致构建的速度慢而且不可靠,开始干扰开发人员的生产率和公司的敏捷度。因此,我们创造了Bazel

Bazel需要一个构建集群吗?

Google内部使用的Bazel确实使用了一个构建集群,所以Bazel在代码库里添加了一个远程构建缓存或者是远程执行系统的钩子。
我们开源的Bazel是在本地执行任务的。我们很自信这对于Bazel的大多数用户来说是足够快的。

Google开发模式是怎样的?

对于我们的服务器端代码库,我们的开发流程如下:

  • 所有的服务器端代码库都在一个巨大的版本控制系统里
  • 每个人都用Bazel构建软件
  • 不同的组负责源码树的不同部分,所有的组件都是作为BUILD目标来用
  • 分支主要是用来管理发布,所以每个人都在最新版本上开发软件

Bazel是以下理念的奠基石:由于Bazel需要所有的依赖都被完整地指定,我们可以预测改动影响了哪些程序和测试,并在提交前执行他们。

更多Google开发模式的背景知识,可以在工具组的博客上看到。译者注:这四篇文章的中文翻译见分布式构建软件

为什么开源Bazel?

构建软件应该是好玩并且容易的,缓慢而且不可预料的构建剥夺了编程的乐趣。

为什么我要使用Bazel?

  • Bazel可以成倍提高构建速度,因为它只重新编译需要重新编译的文件。类似的,它会跳过没有被改变的测试。
  • Bazel产出确定的结果。这消除了增量和干净构建,开发机器和持续集成之间的构建结果的差异。
  • Bazel可以使用同一个工程下的相同的工具来构建不同的客户端和服务器端应用程序。例如,你可以在一次提交里修改一个客户端/服务器协议,然后测试更新后的手机程序和服务器端程序能够正常工作,构建时使用的是同样的工具,利用的都是上面提到的Bazel的特性。

我可以看到例子吗?

是的,一个简单的例子,见:
https://github.com/google/bazel/blob/master/examples/cpp/BUILD

Bazel源代码本身提供了更复杂的例子,例如:
https://github.com/google/bazel/blob/master/src/main/java/BUILD
https://github.com/google/bazel/blob/master/src/test/java/BUILD

Bazel最擅长做什么?

Bazel适合于构建和测试有如下特点的项目:

  • 有庞大代码库的项目
  • 用(多种)需要编译的语言写的项目
  • 在多平台上部署的项目
  • 有大量测试的工程

Bazel在什么平台上运行

目前,在Linux和MacOS上。移植到其他Unix平台上是很简单的,提供的JDK是可用的。

支持Windows平台吗?

我们利用MinGW/MSYS,实验了一个Windows的移植版本,但是目前没有计划去在这个移植版本上花费精力。由于Bazel是基于Unix的,移植Bazel需要大量的工作。例如,Bazel大量使用了符号链接,这在Windows版本中支持的程度各不相同。

不应该使用Bazel的场景

  • Bazel试着在缓存方面智能一些。这意味者不适于不应该被缓存的构建步骤。例如,下面的步骤就不应该被Bazel控制:

    • 从网络上获取数据的编译步骤
    • 连接你的网站测试实例的测试步骤
    • 改变站点云环境的发布步骤
  • Bazel试着缩小耗时的编译[compile]步骤。如果你只使用了解释性语言,例如JavaScript和Python,Bazel就没有吸引力。

    Bazel的功能集合是否稳定?

    核心的功能(C++、Java和shell规则)已经在Google内部大量使用了,所以经历了完整的测试,只可能出现很小很小的问题。类似的,最新的版本每天被我们在成百上千的目标上测试来回归功能,我们每个月会多次发布新版本。

总之,除了被标记为实验性质的功能,任何时候,Bazel都应该工作。对于非实验性质规则的修改肯定会做到向前兼容。更详细的支持的功能可以在我们的功能文档里找到。

作为二进制程序Bazel的稳定性如何?

在Google内部,Bazel极少崩溃。对于我们开源的Bazel也是一样的。

我应该如何开始使用Bazel?

看我们的开始使用的文档。

为什么我需要在包路径里添加一个 tools/目录?

你的工程肯定不是单独工作的。通常情况下,它是使用某个特定版本的JDK/C++ 编译器,使用一个固定版本的测试框架,在某个特定的操作系统版本上运行的。
为了保证我们即使升级了我们的开发机器,构建过程仍然是可重现的,Google会把这些工具中的绝大部分都版本控制起来,包含了工具链(toolchains)和Bazel本身。惯例是把这些放到一个叫做"tools"的目录。
Bazel允许JDK这样的工具放在工程目录之外,但是这个配置项(JDK在哪,C++编译器在哪?)仍然需要放在某个地方,这个地方也就是tools/目录。
Bazel的compile.sh脚本构建了一个配置文件的最小集合,适合运行来自标准系统目录的工具链 ,例如 /usr/bin

Docker没有解决可重现[reproducibility]的问题吗?

利用Docker可以很容易的创建固定操作系统版本的沙箱,例如Ubuntu 12.04, Fedora 21。这解决了系统环境的可重现问题(例如,“需要哪个版本的/usr/bin/C++?”)。

它不能解决针对源代码修改的可重现问题。在Docker内部运行一个不完美的Makefile仍然会出现不可预料的结果。

在Google内部,为了可重现,我们把工具也放到版本控制里。这样我们能够像发现基础库的修改(“修复OpenSSL里的边界检查”)一样,发现针对工具的修改(“升级GCC到4.6.1”)。

能构建部署在Docker上的二进制程序吗?

利用Bazel,可以构建独立的,静态链接的C(++)二进制程序,Java的自包含的jar文件。这些程序在正常的Unix系统里需要极少的依赖,所以在Docker容器里安装同样也是简单的。

Bazel有构建更复杂程序的例子,例如消费一系列数据文件的Java程序,或者把另外一个程序作为子进程运行。可以把这种环境打包成单独的包,以便于可以在不同的系统里进行部署,包括Docker的镜像。但是我们目前没有代码这样做。

能够使用Bazel构建Docker镜像吗?

Bazel构建的程序的可重现性是相对于构建的源码而言的。Bazel的设计里面,它对源码树之外的环境是无法感知的。因此,Bazel不知道Docker自己的环境是否和Docker镜像相一致。所以,如果你跟Docker一起使用Bazel,我们推荐在跟部署的环境一样的环境下运行Bazel,来确保可重现性。

可以跟文件一样写规则产生Docker镜像。然而,由于Docker镜像跟正常的文件系统一样,有很多时间戳,这让可重现充满了挑战。

Bazel能自动地让我的构建可重现吗?

对于Java和C++可执行程序,如果你没有修改工具链,那答案是肯定的。如果构建步骤包含定制的东西(例如,在一个规则内通过shell脚本执行可执行程序),那就需要额外注意:

  • 不要使用没有声明的依赖。沙箱模式的执行(-spawn_strategy=sandboxed, 只能用在Linux下)可以帮助发现未声明的依赖。
  • 不要在产生的文件中存储时间戳。ZIP文件和其他的归档文件尤其需要注意这一点。
  • 避免连接到网络。在沙箱里执行也是可以的。
  • 避免使用了随机数的处理过程,特别是,在很多编程语言中,字典遍历是随机的。

有二进制的版本吗?

没有,但我们应该出二进制的版本。敬请期待!

我使用Eclipse/IntelliJ. Bazel如何跟IDE结合起来?

我们目前没有跟IDE交互的API,但是iOS规则可以根据BUILD目标来产生Xcode可用的工程。

Bazel如何跟Xcode交互?

Bazel产出可以使用任何输入和依赖的Xcode工程,可以直接从Xcode构建APP然后部署到模拟器和设备上。打开Bazel构建任何iOS目标后打印出的工程文件的路径就可以使用这个功能。不支持从Xcode里调用Bazel(例如基于proto文件来重新产生Objc源文件),也不支持从Bazel直接打开Xcode。

我使用Jenkins/CircleCI/TravisCI. Bazel如何跟持续集成系统结合起来?

如果构建或者测试过程失败,Bazel返回非0值,这对于基本的持续集成系统来说,已经够用了。由于Bazel不需清除构建就可以保持构建结果的正确性,所以持续集成系统可以配置成在启动一个构建/测试的时候不进行清除操作
关于返回值的更多细节,参见用户手册

未来Bazel会加入哪些功能?

我们一开始的目标是满足Google内部使用。这包括Google的主要编程语言(C++, Java, Go)和主要平台(Linux,Android,iOS)。由于一些原因,并不是所有的这些都是开源的。更多细节见路线图

关于Python呢?

可以把书写的Python的规则当作扩展(见下面的例子)。之后的例子是如何产生自包含python的zip文件

https://github.com/google/bazel/blob/master/tools/build_rules/py_rules.bzl
https://github.com/google/bazel/tree/master/examples/py

我们正在准备开源一套Google内部使用的Python规则的子集,这些规则可以当作辅助脚本而成为构建的一部分

我们目前没有计划要提供打包整个自满足的Python二进制的过程。

关于Go呢?

如果你的代码库里的代码,100%都是Go语言,那么 go 工具在构建和测试方面表现很出色,Bazel不会给你带来 go 工具这么大的收益。
在Google用Go写的服务器端代码是用Bazel构建的。然而,由于Go语言的代码和我们C++库的交互而导致使用Bazel构建Go语言部分的过程很复杂,并和 go 工具的惯例不兼容。因为这个原因,我们宁愿不开源目前的Go相关的规则

可以使用Bazel来构建我的LISP/Python/Haskell/Scala/Rust的工程吗?

Bazel有一套扩展机制来允许添加新的规则而不需要重新编译Bazel。文档见这里
但是到目前为止,这套扩展机制是实验性质的。

我需要更多的功能。我可以添加编译到Bazel里面的规则吗?

如果扩展机制对于你的场景来说不够用,请把相关建议邮件到这个组:bazel-discuss@googlegroups.com

我可以给Bazel代码贡献吗?

见我们的贡献指南

为什么目前Bazel的开发过程并不都是开源状态

我们仍然在大量重构Bazel内部公共的代码和我们内部扩展之间的接口部分。所以这部分要开源开发很困难。更多详细信息见我们的governance plan

如何联系Bazel开发组?

通过 bazel-discuss@googlegroups.com 来联系

怎么汇报bug?

给bazel-discuss@googlegroups.com发邮件,或者在GitHub上报bug

在代码中的单词"Blaze"是什么意思?

这是这个工具的内部名称。请使用Bazel来指代Bazel这个工具

为什么其他Google的工程(Android,Chrome)使用其他的构建工具?

之前Bazel一直都是内部使用的,所以开源项目,例如Chromium,Android等都不能使用它。而且,缺乏对Windows支持而导致
不能构建Windows应用程序,例如Chrome。

"Bazel"怎么发音?

跟美国英语中的“basil”(草本植物)一样的:"BAY-zel".


如果您看了本篇博客,觉得对您有所收获,请点击右下角的“推荐”,让更多人看到!

资助Jack47写作,打赏一个鸡蛋灌饼钱吧
微信打赏
支付宝打赏

Google软件构建工具Bazel FAQ的更多相关文章

  1. Google软件构建工具Bazel原理及使用方法介绍

    近期,Google开源了强大的自动化构建工具Bazel. 正好博主近期在使用china版的Bazel--腾讯自主开发的Blade,所以准备跟大家分享一下Google Bazel这个分布式构建系统的原理 ...

  2. Google软件构建工具Bazel

    转载Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用 ...

  3. 构建工具Bazel入门

    Bazel入门   原文:http://bazel.io/docs/getting-started.html 译者:chai2010 安装 安装过程请参考: http://bazel.io/docs/ ...

  4. 为什么google bazel构建工具流行不起来

    作者Jack47 转载请保留作者和原文出处 之前博主写了系列文章Google软件构建工具Bazel原理及使用方法介绍.最近使用了一段时间后,觉得这个东西不是一种通用的构建工具,很难对接到情况复杂的大的 ...

  5. 高效使用Java构建工具,Maven篇|云效工程师指北

    大家好,我是胡晓宇,目前在云效主要负责Flow流水线编排.任务调度与执行引擎相关的工作. 作为一个有多年Java开发测试工具链开发经验的CRUD专家,使用过所有主流的Java构建工具,对于如何高效使用 ...

  6. Google分布式构建软件之二:构建系统如何工作

    分布式软件构建第二部分:构建系统如何工作 注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 上篇文章中提到了在Google,所 ...

  7. Google分布式构建软件之三:分布式执行构建步骤

    注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 之前两篇文章分别介绍了Google 分布式软件构建系统Blaze相关的为了提 ...

  8. Google分布式构建软件之四:分发构建结果

    注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 之前的文章,介绍了Google在分布式构建软件过程中,如何把构建过程分发到许 ...

  9. 《Google软件测试之道》基础

    <Google软件测试之道>,一直听朋友讲起这本书,出于琐事太多,一直没机会拜读,最近部门架构觉得我们IT部门的技术太low,就给我们挑选了一些书籍,让我们多看看... 个人的一种学习习惯 ...

随机推荐

  1. C++预定义宏

    C/C++宏体中出现的#,#@,##: - #的功能是将其后面的宏参数进行字符串化操作(stringfication),就是对它所引用的宏变量通过替换后在其左右各加上一个双引号 -##被称为连接符(c ...

  2. BitHacks

    备份文件时看到的.我以前居然下过这东西. 2016-12-4 12:05:52更新 纯文本格式真棒.假如使用word写的我能拷过来格式还不乱?? Markdown真好. Bit Hacks By Se ...

  3. maven权威指南学习笔记(五)—— POM

    1. 简介 Archetype插件通过 pom.xml 文件创建了一个项目.这就是项目对象模型 (POM),一个项目的声明性描述. 当Maven运行一个目标的时候,每个目标都会访问定 义在项目POM里 ...

  4. c语言快速入门1

    如果你想快速入门计算机,可以参考我的上一篇帖子,先了解一些必备的软知识,然后再来进行语言的快速入门 计算机入门基础知识 目录 1.1.1    计算机与程序 现代计算机可以自动完成计算任务 程序就是按 ...

  5. Linux service命令

    service命令(其实与其说是命令,不如说是脚本),因为service本身就是一个脚本,这个脚本在/sbin路径下,待后续shell脚本功底好了将去认真去看看这个脚本的内容(可不能被人忽悠了.) s ...

  6. 如果做好测试PM【转载】

    本文来源于:https://yq.aliyun.com/articles/14578?spm=5176.100238.yqhn2.14.Lcie4Y   摘要今年整体带了几个项目.我本人不是专业的PM ...

  7. Arduino下LCD1602综合探究(上)——1602的两种驱动方式,如何使LCD的控制编程变得更简单

    一.前言: LCD ( Liquid Crystal Display 的简称)液晶显示器,已经逐渐替代CRT成为主流的显示设备之一,因此也成为了单片机发烧友绕不过的话题之一:而LCD1602更是很多单 ...

  8. sass基础用法

    嵌套: 1.选择器嵌套: 2.属性嵌套; .box {     border-top: 1px solid red;     border-bottom: 1px solid green; } .bo ...

  9. Time-travel Models

    1. Standard Iterative Branching model   Source Code   Butterfly Effect   Next   Edge of Tomorrow   D ...

  10. linux菜鸟日记

    本地yum源的安装: 要安装本地yum源,首先需要熟悉本地yum文件的配置和光盘的挂载 第一步挂载光盘: 首先需要指定一个光盘挂载目录 通常情况下我习惯使用默认挂载目录,所以一般我使用的光盘挂载命令是 ...