什么是 Bazel
Bazel 是一个开源的构建和测试工具,类似于Make、Maven 及 Gradle。它使用一种人易于理解的高级构建语言。Bazel 支持多种开发语言的项目,能够基于多个平台来构建。Bazel 支持跨多个制品库和大规模用户的大型代码仓库。
为什么我们需要 Bazel
Bazel 具有以下优势:
高级构建语言 Bazel 使用一种抽象的、人易于理解的、语义级别的高级语言来描述项目的构建属性。与其他工具不同,Bazel 基于库,二进制文件,脚本和数据集的概念进行操作,使您免于陷入将单个调用编写到编译器和链接器等工具的复杂性。
Bazel 高效可靠 Bazel 缓存以前完成的所有工作,并跟踪文件内容和构建命令的更改。通过这种方式,Bazel 知道何时需要重建某些东西,并仅重建那些东西。为了进一步加快构建速度,您可以将项目设置为以并行和增量的方式构建。
Bazel是跨平台的 Bazel 可以在 Linux,macOS 和 Windows 上运行。Bazel 可以为同一个项目中的多个平台(包括桌面,服务器和移动设备)构建二进制文件和可部署软件包。
Bazel扩展性强 Bazel 在使用100k+源文件处理构建时仍然保持良好的性能表现。它适用于多个制品存储库和10K用户规模。
Bazel是可扩展的 您可以扩展 Bazel 以支持您选择的语言。
Bazel 核心概念
Bazel 根据在称为工作空间(WORKSPACE)的目录中组织的源代码构建软件。工作空间中的源文件以包的嵌套层次结构进行组织,其中每个包都是包含一组相关源文件和一个 BUILD 文件的目录。BUILD 文件指定可以从源构建哪些软件输出。
工作空间
工作空间是文件系统上的目录,其中包含要构建的软件的源文件,以及指向包含构建输出的目录的符号链接。每个工作空间目录都有一个名为 WORKSPACE 的文本文件,该文件可能为空,或者可能包含对构建输出所需的外部依赖项的引用。
包
工作空间中代码组织的主要单元是包。包是相关文件的集合,以及它们之间的依赖关系的规范。包被定义为包含名为 BUILD 的文件的目录,该文件位于工作空间中的顶级目录下。包中包含其目录中的所有文件,以及其下的所有子目录,除了那些本身包含 BUILD 文件的子目录。
例如,在以下目录树中有两个包,my/app 和子包 my/app/tests。请注意,my/app/data 不是包,而是属于包 my/app 的目录。
目标
包是一个容器。包的元素称为目标。大多数目标是两种主要类型之一,即文件和规则。此外,还有另一种目标,包组,但它们的数量要少得多。
文件进一步分为两种。源文件通常由开发者的努力编写,并签入代码存储库。生成的文件(有时称为派生文件)不会签入,而是由构建工具根据特定规则从源文件生成。
第二种目标是规则。规则指定一组输入和一组输出文件之间的关系,包括从输入中导出输出的必要步骤。规则的输出始终是生成的文件。规则的输入可以是源文件,但也可以是生成的文件; 因此,一条规则的输出可能是另一条规则的输入,允许构建长链规则。
在大多数情况下,规则的输入是源文件还是生成的文件都是无关紧要的; 重要的只是该文件的内容。这一事实使得用规则生成的生成文件替换复杂的源文件变得容易,例如当手动维护高度结构化文件的负担变得太烦人时,有人编写程序来派生它。该文件的使用者无需更改。相反,生成的文件可以很容易地被仅具有本地更改的源文件替换。
规则的输入还可以包括其他规则。这种关系的确切含义通常非常复杂,并且依赖于语言或规则,但直观上很简单: C++ 库规则 A 可能有另一个 C++ 库规则B用于输入。这种依赖性的影响是B的头文件在编译期间可用于 A,B 的符号在链接期间可用于 A,B 的运行时数据在执行期间可用于 A。
所有规则的不变量是规则生成的文件始终属于与规则本身相同的包; 无法将文件生成到另一个包中。但是,规则的输入来自另一个包的情况并不少见。
包组是一组包,其目的是限制某些规则的可访问性。包组由 package_group 函数定义。 它们有两个属性:它们包含的包列表及其名称。 唯一允许引用它们的方法来自规则的 visibility 属性或 package 函数的 default_visibility 属性; 他们不生成或使用文件。
总结
Bazel 默认支持多种开发语言,如 Java,C++,Javascript, Android 等等,您还可以根据需要扩展它。在很多开源项目中都有用到它,由于其支持并行构建,增量构建等特性,与传统构建工具区别很大,因此备受青睐,后续会详细介绍其他概念和入门使用,敬请关注。