本页面假定您熟悉 Bazel,并提供了有关如何构建项目以充分利用 Bazel 功能的准则和建议。
总体目标如下:
- 使用精细的依赖项来实现并行性和增量性。
- 以便妥善封装依赖项。
- 使代码结构清晰且可测试。
- 创建易于理解和维护的 build 配置。
这些指南并非要求:很少有项目能够遵循所有这些指南。正如 lint 的 man 页所说,“第一个能够在严格检查下生成不出错的真实程序的人将获得特别奖励。”不过,尽可能采用这些原则应该可以让项目更易于阅读、不易出错且构建速度更快。
本页使用了此 RFC 中所述的要求级别。
运行 build 和测试
项目应始终能够在其稳定分支上成功运行 bazel build //...
和 bazel test //...
。对于必要但在特定情况下无法构建的目标(例如,需要特定的 build 标志、无法在特定平台上构建、需要许可协议),应尽可能具体地进行标记(例如“requires-osx
”)。这种标记方式可让您以比“手动”标记更精细的级别过滤目标,并让检查 BUILD
文件的用户了解目标的限制。
第三方依赖项
您可以声明第三方依赖项:
- 在
MODULE.bazel
文件中将其声明为远程代码库。 - 或者,将它们放在工作区目录下的
third_party/
目录中。
取决于二进制文件
应尽可能从源代码构建所有内容。通常,这意味着您需要创建 BUILD
文件,并根据其源代码构建 some-library.so
,而不是依赖于库 some-library.so
,然后依赖于该目标。
始终从源代码构建可确保 build 不会使用使用不兼容标志或采用其他架构构建的库。此外,一些功能(例如覆盖率、静态分析或动态分析)仅适用于源代码。
版本控制
尽可能从主干构建所有代码。必须使用版本时,请避免在目标名称中添加版本号(例如 //guava
,而不是 //guava-20.0
)。这种命名方式有助于更轻松地更新库(只需更新一个目标)。它对钻石依赖项问题也更具弹性:如果一个库依赖于 guava-19.0
,另一个库依赖于 guava-20.0
,最终可能会导致库尝试依赖于两个不同的版本。如果您创建了误导性的别名来将两个目标指向一个 guava
库,则 BUILD
文件会误导用户。
使用 .bazelrc
文件
对于项目专用选项,请使用 workspace/.bazelrc
的配置文件(请参阅 bazelrc 格式)。
如果您希望为项目支持不想签入源代码控制系统的每位用户选项,请添加以下代码行:
try-import %workspace%/user.bazelrc
(或任何其他文件名)并将 user.bazelrc
添加到 .gitignore
。workspace/.bazelrc
软件包
包含可构建文件的每个目录都应为软件包。如果 BUILD
文件引用子目录(例如 srcs = ["a/b/C.java"]
)中的文件,则表示应将 BUILD
文件添加到该子目录。这种结构存在的时间越长,无意中创建循环依赖项的可能性就越大,目标的范围会不断扩大,并且需要更新的反向依赖项数量也会越来越多。