bazel -rule 学习

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]))]

 DefaultInfo - Bazel main

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.

Providers:一个 rule 暴露给依赖它的rules的一些信息。这些信息可以是(输出文件、库、在工具命令行上传递的参数,以及依赖他的 traget 所需要的其他信息)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值