Bazel Build: 最佳实践

应用Bazel构建系统,其总体目标包括:

  • 采用细粒度控制依赖,最大化并行性和增量构建;
  • 保持依赖关系的良好封装,严格控制规则的可见性;
  • 保持代码组织拥有良好的结构和可测试性;
  • 创建易于理解、易于维护的构建系统。

全量构建

一般地,一个良好的项目,如下两个构建命令应该总是成功的;否则,不应该将代码提交到Git上。

$ bazel build //repo_name/...
$ bazel test //repo_name/...

其中,repo_name为顶级包名。

显示化平台依赖

在一些特殊的情况下,例如,需要特定的构建选项,平台选项,License等,应尽可能显式化地标记相应的规则,并且能够方便用户细粒度地筛选相应的规则,用户通过查看BUILD文件也能够快速了解规则的约束和条件。

尽最大化源码依赖

对于C/C++项目,尽量依赖于源码。如果依赖于二进制库,可能导致不兼容的编译选项和平台依赖。依赖于源码,保证二进制的兼容性和平台的一致性;而且保证诸如静态检查工具,测试覆盖率,及其性能分析更好地工作。

控制头文件的可见性

将公开的头文件放在在hdrs列表中,而将不公开的头文件放置在srcs列表中。例如,

cc_library(
   name = "bar",
   srcs = [
       "bar.cc",
       "bar-impl.h",
       "bar-impl.cc",
   ],
   hdrs = ["bar.h"],
)

此时,foo依赖于bar时,仅能包含bar.h,而不能包含bar-impl.h

cc_binary(
    name = "main",
    srcs = [
        "main.cc"
        "foo.h",
        "foo.cc",
    ],
    deps = [":bar"],
)

只包含直接依赖

加入存在如下依赖关系,foo->bar->baz。显然,foo传递依赖于baz。此时,foo.cc能够包含foo.h, bar.h;但是,绝对不应该包含baz.h,除非foo显式地将baz添加到deps列表中。

不幸的是,Bazel目前实现由于技术实现的原因,并没有做到传递依赖的相关约束,仅推荐为最佳实践。如果在foo.cc中包含了baz.h,依然能够构建成功。但是,这个在未来版本中,可能被强制。

cc_binary(
    name = "foo",
    srcs = [
        "main.cc"
        "foo.cc",
        "foo.h",
    ],
    deps = [":bar"],
)

cc_library(
    name = "bar",
    srcs = [
        "bar.cc",
        "bar-impl.h",
        "bar-impl.cc",
    ],
    hdrs = ["bar.h"],
    deps = [":baz"],
)

cc_library(
    name = "baz",
    srcs = [
        "baz.cc",
        "baz-impl.h",
        "baz-impl.cc",
    ],
    hdrs = ["baz.h"],
)

你可能感兴趣的:(Bazel Build: 最佳实践)