相约 2023 年 BazelCon 将于 10 月 24 日至 25 日在 Google 慕尼黑举办!了解详情

工作区、软件包和目标

报告问题 查看源代码

Bazel 使用组织在目录树(称为工作区)中的源代码构建软件。工作区中的源文件按软件包的嵌套层次结构进行组织,其中每个软件包都是一个目录,其中包含一组相关的源文件和一个 BUILD 文件。BUILD 文件指定可以从源代码构建哪些软件输出。

工作区

工作区是文件系统上的目录树,其中包含要构建的软件的源文件。每个工作区都有一个名为 WORKSPACE 的文本文件,该文件可能为空,或可能包含对构建输出所需的外部依赖项的引用。

包含名为 WORKSPACE 的文件的目录被视为工作区的根。因此,Bazel 会忽略工作区中位于包含 WORKSPACE 文件的子目录中的任何目录树,因为它们形成了另一个工作区。

Bazel 还支持将 WORKSPACE.bazel 文件用作 WORKSPACE 文件的别名。如果两个文件都存在,系统会使用 WORKSPACE.bazel

代码库

代码位于代码库中。包含 WORKSPACE 文件的目录是主代码库的根目录,也称为 @。其他(外部)代码库则使用工作区规则在 WORKSPACE 文件中定义,或者从 Bzlmod 系统中的模块和扩展程序生成。如需了解详情,请参阅外部依赖项概览

与 Bazel 捆绑的工作区规则在构建百科全书工作区规则部分和嵌入式 Starlark 代码库规则文档中进行了说明。

由于外部代码库本身是代码库,因此它们通常也包含 WORKSPACE 文件。但是,Bazel 会忽略这些额外的 WORKSPACE 文件。具体而言,系统不会自动添加依赖传递的代码库。

软件包

代码库中的主要代码组织单元是软件包。软件包是相关文件的集合,以及如何使用这些文件生成输出工件的规范。

软件包指包含名为 BUILDBUILD.bazelBUILD 文件的目录。软件包中包含其目录中的所有文件及其下的所有子目录,但包含 BUILD 文件的文件除外。根据该定义,任何文件或目录都不得是两个不同软件包的一部分。

例如,以下目录树中有两个软件包:my/app 和子软件包 my/app/tests。请注意,my/app/data 不是软件包,而是属于软件包 my/app 的目录。

src/my/app/BUILD
src/my/app/app.cc
src/my/app/data/input.txt
src/my/app/tests/BUILD
src/my/app/tests/test.cc

目标

软件包是目标软件包的容器,在软件包的 BUILD 文件中定义。大多数目标是两种主要类型之一:文件规则

文件进一步分为两种。源文件通常由用户编写并签入代码库。生成的文件(有时称为派生文件或输出文件)不会被签入,但是从源文件生成的。

第二种目标使用规则声明。每个规则实例都用于指定一组输入文件与一组输出文件之间的关系。规则的输入可以是源文件,但也可以是其他规则的输出。

规则的输入是源文件还是生成的文件在大多数情况下都无关紧要;重要的是文件的内容。因此,您可以轻松地将复杂的源文件替换为规则生成的文件,例如手动维护高度结构化的文件的负担太重,以及有人编写程序派生这些文件。该文件的使用者无需进行任何更改。相反,生成的文件可能会被仅有本地更改的源文件轻松替换。

输入的规则还可以包含其他规则。此类关系的确切含义通常非常复杂,并且依赖于语言或规则,但直观地说它很简单:C++ 库规则 A 可能具有另一个 C++ 库规则 B 作为输入。此依赖项的影响是,编译期间 B 的头文件可供 A 使用,在链接期间,B 的符号可供 A 使用,并且 B 的运行时数据在执行期间可供 A 使用。

所有规则的不变是:规则生成的文件始终属于规则本身所在的软件包;无法将文件生成到另一个软件包中。但是,规则的输入来自其他软件包的情况并不少见。

软件包组是一组旨在限制特定规则访问的软件包。软件包组由 package_group 函数定义。它们有三个属性:它们包含的软件包列表、它们的名称,以及它们包含的其他软件包组。只能引用这些规则的 visibility 属性或 package 函数的 default_visibility 属性;它们不会生成或使用文件。如需了解详情,请参阅 package_group 文档

标签