Bazel 概念
工作区 (Workspace): 包含 WORKSPACE 文件的目录
包 (Package): 包含 BUILD.bazel 文件的目录
目标 (Target): 文件或规则
规则 (Rules): 可以构建的目标 (类似于 make 中的 phony 目标)
文件 (Files): 源文件或生成的文件
标签 (Label): 目标的名称。唯一标识一个目标。
https://docs.bazel.build/versions/main/build-ref.html
小型 Bazel 项目示例
my-project/
├── WORKSPACE
└── my-package/
├── hello.c
└── BUILD.bazel
c
# my-project/WORKSPACE
# Empty file
# Tells Bazel where the root is
# For kernel, the WORKSPACE file should be placed
# right below ${ROOT_DIR}
c
# my-project/my-package/BUILD.bazel
cc_binary(
name = "hello",
srcs = ["hello.c"],
)
c
$ bazel build //my-package:hello
/my-package:hello 是目标的完整名称(即目标的标签)。你可以在工作区内的任何位置引用或使用它。
c
// my-project/my-package/hello.c
#include <stdio.h>
int main(int argc, char** argv) {
printf("hello!\n");
return 0;
}
c
$ bazel run //my-package:hello
hello!
c
bazel build <label>
如果目标已过期,则构建它。如果目标是最新的,则跳过构建。
bazel run <label>
如果目标已过期,则构建它。如果目标是最新的,则跳过构建。
运行一个目标。仅当该目标是脚本/可执行文件等时才有意义。
Depend on targets (same package)
一个 target 可以依赖于同一 package 内的其他 targets 或 files;在引用时,其名称前的冒号是可选的,但惯例是在规则定义的 target 前加上冒号,而对于实际的 file 则不加。
c
# my-project/my-package/BUILD.bazel
filegroup(
name = "hello_srcs",
srcs = ["hello.c"],
# Usually no colon for files. ":hello.c" is also valid.
)
cc_binary(
name = "hello",
srcs = [":hello_srcs"],
# Usually add colon for targets. "hello_srcs" is also valid.
)
Depend on targets from other packages
c
my-project/
├── WORKSPACE
├── my-lib/
│ ├── lib.h
│ ├── lib.c
│ └── BUILD.bazel
└── my-binary/
├── hello.c
└── BUILD.bazel
c
# my-project/my-lib/BUILD.bazel
cc_library(
name = "libhello",
srcs = ["lib.c"],
visibility = ["//my-binary:__pkg__"],
)
c
# my-project/my-binary/BUILD.bazel
cc_binary(
name = "hello",
srcs = ["hello.c"],
static_libs = ["//my-lib:libhello"],
)
Bazel extensions *.bzl
c
# my-project/my-package/myrules.bzl
def my_fancy_binary(name, srcs, **kwargs):
native.filegroup(name = name + "_srcs",
srcs = srcs,
**kwargs)
cc_binary(name = name,
srcs = [":" + name + "_srcs"],
**kwargs)
c
# my-project/my-package/BUILD.bazel
# load is Bazel's "import"
load("//my-package:myrules.bzl", "my_fancy_binary")
my_fancy_binary(name = "fancy_hello", srcs = ["hello
... is equivalent to ...
c
cc_binary(name = "fancy_hello", srcs = ["hello.c"])
filegroup(name = "fancy_hello_srcs", srcs = ["hello.c"])
Bazel 构建文件:.bzl 与 BUILD.bazel 的区别
在 Bazel 中,.bzl 文件和 BUILD.bazel 文件在构建流程中扮演着不同的、但又相互关联的角色。我们可以将它们与 Makefile 和 Kbuild 进行类比来更好地理解。
*.bzl 文件
类比: 类似于 Makefile.* 文件,用于定义构建逻辑。
目的: 包含如何构建事物的定义。
内容:
Rule definitions(规则定义):定义新的自定义构建规则(例如,你可以想象它包含了 cc_binary 这种内置规则的底层实现逻辑)。
Macro definitions(宏定义):定义可重用的构建函数,它们封装了一个或多个规则(例如,my_fancy_binary 可能内部调用 cc_binary 和 filegroup 等)。
其他用于构建逻辑的 Starlark 函数和变量。
BUILD.bazel 文件
类比: 类似于 Kbuild 文件(或内核构建中的子目录 Makefile)。
目的: 通过调用或实例化已定义的构建规则和宏,在 package 内注册特定的 targets。
内容:
Rule instantiations(规则实例化):调用预定义或自定义规则来创建具体的 targets(例如,cc_library(name = "libhello", ...) 实例化 cc_library 规则以创建 libhello target;cc_binary(name = "hello", ...), 创建 hello target)。
Macro invocations(宏调用):调用已定义的宏来创建复合 targets(例如,fancy_hello(...) 调用 fancy_hello 宏)。
为这些 targets 指定属性。
排除
c
# my-project/my-package/BUILD.bazel
cc_binary(
name = "hello",
srcs = glob(["*.c"],
exclude = ["exclude.c"]),
)