如何使用Genrule输出作为Bazel中expand_template替换的字符串?

时间:2019-04-26 11:02:20

标签: 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"},
)

已构建

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

和local.go.in

package version

func init() {
    V = "{version}"
}

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

1 个答案:

答案 0 :(得分:0)

这里的问题是substitutions的{​​{1}}自变量必须在分析阶段(即运行ctx.actions.expand_template()的时候)知道,该参数发生在_expand_impl之前genrule的命令将运行(即在执行阶段)。

有几种方法可以做到这一点。最简单的是做所有事情:

git rev-parse HEAD

这取决于genrule( name = "gen_local_go", srcs = ["local.go.in"], outs = ["local.go"], local = 1, cmd = 'sed "s/{VERSION}/$(git rev-parse HEAD)/" "$<" > "$@"', ) 在主机上是否可用,但是可以输入一个文件,修改文本并将其输出到另一个文件的任何其他程序都可以使用。

另一种选择是结合使用--workspace_status_command 这里有更多详细信息: How to run a shell command at analysis time in bazel? 这种方法的优点是它避免了局部风格。