本页面假定您熟悉 Bazel,并提供了有关如何设计项目结构的指南和建议,以便充分利用 Bazel 的功能。
总体目标是:
- 使用精细的依赖项来支持并行性和增量性。
- 为了确保依赖项得到妥善封装。
- 确保代码结构合理且易于测试。
- 创建一个易于理解和维护的 build 配置。
这些准则并非强制性要求:很少有项目能够符合所有准则。正如 lint 的手册页面所述,“我们将为第一个生成真正的程序提供特别奖励,该程序会进行严格检查,确保不会产生任何错误。”不过,尽可能多地采用这些原则会使项目更易于阅读、更不容易出错并更快的构建速度。
本页使用了此 RFC 中所述的要求级别。
运行构建和测试
项目应始终能够在其稳定分支上成功运行 bazel build //...
和 bazel test //...
。对于必不可少但在某些情况下不会构建的目标(例如,需要特定的构建标记、不在特定平台上构建、需要许可协议),应尽可能具体地标记(例如“requires-osx
”)。这种标记可让您在比“手动”标记更精细的级别过滤目标,并让检查 BUILD
文件的人员能够了解目标的限制。
第三方依赖项
您可以声明第三方依赖项:
- 在
WORKSPACE
文件中将其声明为远程仓库。 - 或者将它们放在工作区目录下名为
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
文件添加到该子目录中。此结构存在的时间越长,就越有可能无意中创建循环依赖项,目标的范围会发生变化,并且必须更新越来越多的反向依赖项。