如何在 Bazel 中使用 genrule 输出作为字符串来 Expand_template 替换?

zhu*_*nyi 5 bazel

看来genrule只能输出一个Target,而expand_template替换只接受string_dict,如何使用genrule输出来expand_template?

gen.bzl

def _expand_impl(ctx):
    ctx.actions.expand_template(
        template = ctx.file._template,
        output = ctx.outputs.source_file,
        substitutions = {
            "{version}": ctx.attr.version,
        }
    )

expand = rule(
    implementation = _expand_impl,
    attrs = {
        "version": attr.string(mandatory = True),
        "_template": attr.label(
            default = Label("//version:local.go.in"),
            allow_single_file = True,
        ),
    },
    outputs = {"source_file": "local.go"},
)
Run Code Online (Sandbox Code Playgroud)

建造

load("@io_bazel_rules_go//go:def.bzl", "go_library")

filegroup(
    name = "templates",
    srcs = ["local.go.in"],
)

genrule(
    name = "inject",
    outs = ["VERSION"],
    local = 1,
    cmd = "git rev-parse HEAD",
)

load(":gen.bzl", "expand")

expand(
    name = "expand",
    version = ":inject",
)

go_library(
    name = "go_default_library",
    srcs = [
        "default.go",
        ":expand", # Keep
    ],
    importpath = "go.megvii-inc.com/brain/data/version",
    visibility = ["//visibility:public"],
)
Run Code Online (Sandbox Code Playgroud)

和 local.go.in

package version

func init() {
    V = "{version}"
}
Run Code Online (Sandbox Code Playgroud)

我希望 local.go.in 中的 {version} 可以被输出替换git rev-parse HEAD

ahu*_*sky 0

这里的问题是,在分析阶段(即何时运行)必须知道substitutions的参数,这发生在genrule 的命令运行之前(即在执行阶段)。ctx.actions.expand_template()_expand_implgit rev-parse HEAD

有几种方法可以做到这一点。最简单的是在 genrule 中完成所有操作:

genrule(
    name = "gen_local_go",
    srcs = ["local.go.in"],
    outs = ["local.go"],
    local = 1,
    cmd = 'sed "s/{VERSION}/$(git rev-parse HEAD)/" "$<" > "$@"',
)
Run Code Online (Sandbox Code Playgroud)

这依赖于sed在主机上可用,但是可以输入一个文件、修改文本并将其输出到另一个文件的任何其他类型的程序都可以工作。

另一种选择是使用--workspace_status_command的组合 ,这里有更多详细信息: How to run a shell command atanalysis time in bazel? 这种方法的优点是它避免了局部通用规则。