rule 的概念:
bazel rule 可以看成是一个函数:根据输入 执行action 得到输出
// foo.bzl
def _foo_binary_impl(ctx):
print("analyzing", ctx.label)
foo_binary = rule(
implementation = _foo_binary_impl,
)
print("bzl file evaluation")
//BUILD
load(":foo.bzl", "foo_binary")
print("BUILD file")
foo_binary(name = "bin1")
foo_binary(name = "bin2")
ctx: ctx - Bazel main
ctx 可以理解成rule 的输入对象,这个对象包含的详细属性
bazel query :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:8:1: bzl file evaluation
DEBUG: /usr/home/bazel-codelab/BUILD:2:1: BUILD file
//:bin2
//:bin1
bazel query 只是 load Build files, 不会分析 target, 如果有多个 Build 文件都会 load 同一个 .bzl 文件只会 load 一次。(load 一次后会被 cache )
bazel build :all
DEBUG: /usr/home/bazel-codelab/foo.bzl:8:1: bzl file evaluation
DEBUG: /usr/home/bazel-codelab/BUILD:2:1: BUILD file
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin1
DEBUG: /usr/home/bazel-codelab/foo.bzl:2:5: analyzing //:bin2
INFO: Analyzed 2 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets...
bazekl build 命令才会分析 target
ctx:
actions ctx.actions: Contains methods for declaring output files and the actions that produce them. (用于声明输出文件,并且产生此文件)
def _foo_binary_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = out,
content = "Hello\n",
)
return [DefaultInfo(files = depset([out]))]
bazel build bin1
INFO: Found 1 target...
Target //:bin1 up-to-date:
bazel-bin/bin1
$ cat bazel-bin/bin1
Hello!
list ctx.aspect_ids:Returns a list ids for all aspects applied to the target. Only available in aspect implementation functions.(返回应用于目标的所有aspect列表 ID。 仅在aspect 实现功能中可用。)
struct ctx.attr:A struct to access the values of the attributes. The values are provided by the user (if not, a default value is used). The attributes of the struct and the types of their values correspond to the keys and values of the attrs dict provided to the rule function. See example of use.(用于访问属性值的结构。 这些值由用户提供(如果没有,则使用默认值)。 struct 的属性及其值的类型对应于提供给规则函数的 attrs dict 的键和值)
// fool.bzl
def _foo_binary_impl(ctx):
out = ctx.actions.declare_file(ctx.label.name)
ctx.actions.write(
output = out,
content = "Hello {}!\n".format(ctx.attr.username),
)
return [DefaultInfo(files = depset([out]))]
foo_binary = rule(
implementation = _foo_binary_impl,
attrs = {
"username": attr.string(),
},
)
// BUILD
load(":foo.bzl", "foo_binary")
foo_binary(
name = "bin",
username = "Alice",
)
root ctx.bin_dir: The root corresponding to bin directory.
string ctx.build_file_path: Returns path to the BUILD file for this rule, relative to the source root.
configuration ctx.configuration :Returns the default configuration. See the configuration type for more details. (configuration - Bazel main)
bool ctx.coverage_instrumented(target=None): eturns whether code coverage instrumentation should be generated when performing compilation actions for this rule or, if target is provided, the rule specified by that Target. (If a non-rule or a Starlark rule Target is provided, this returns False.) Checks if the sources of the current rule (if no Target is provided) or the sources of Target should be instrumented based on the --instrumentation_filter and --instrument_test_targets config settings. This differs from coverage_enabled in the configuration, which notes whether coverage data collection is enabled for the entire run, but not whether a specific target should be instrumented. Target - Bazel main
StarlarkValue ctx.created_actions():
ExecGroupCollection ctx.exec_groups: A collection of the execution groups available for this rule, indexed by their name. Access with ctx.exec_groups[name_of_group]
struct ctx.executable
string ctx.expand_location(input, targets=[])
ctx.features:
Aspect:Aspects - Bazel main
BUILD 文件提供项目源代码的描述了:哪些源文件是项目的一部分,从哪些文件区构建target,并给出这些文件间的依赖等。bazel 根据BUILD 文件提供的这些信息先计算出生成traget 所需要的一系列 action, 并且执行这些 action.
bazel是如何做到的?
bazel 通过在目标之间构建依赖关系图并访问该图以收集这些action来实现。
那如何构建这些依赖关系图,并且如何访问这些依赖关系图的?
java_library(name = 'W', ...)
java_library(name = 'Y', deps = [':W'], ...)
java_library(name = 'Z', deps = [':W'], ...)
java_library(name = 'Q', ...)
java_library(name = 'T', deps = [':Q'], ...)
java_library(name = 'X', deps = [':Y',':Z'], runtime_deps = [':T'], ...)
在 rule的实现函数中会记录下来 provider,通常通过将这些信息累积到一个depset.,传递给依赖他的其他 target.
Depset是一种专门的数据结构,用于跨目标的传递依赖项,并且有效地收集数据。Depsets - Bazel main
一个 target 的 providers 是rule 的实现函数的返回值,是一个 list,每个 元素都是 provider.