尝试编写自定义规则

Trying to write a custom rule

我正在尝试为 gqlgen 编写自定义规则。这个想法是 运行 它从 GraphQL 模式生成 Go 代码。

我的预期用途是:

gqlgen(
    name = "gql-gen-foo",
    schemas = ["schemas/schema.graphql"],
    visibility = ["//visibility:public"],
)

"name"是规则的名称,我希望其他规则依赖于它; "schemas" 是一组输入文件。

到目前为止我有:

load(
    "@io_bazel_rules_go//go:def.bzl",
    _go_context = "go_context",
    _go_rule = "go_rule",
)

def _gqlgen_impl(ctx):
    go = _go_context(ctx)
    args = ["run github.com/99designs/gqlgen --config"] + [ctx.attr.config]
    ctx.actions.run(
        inputs = ctx.attr.schemas,
        outputs = [ctx.actions.declare_file(ctx.attr.name)],
        arguments = args,
        progress_message = "Generating GraphQL models and runtime from %s" % ctx.attr.config,
        executable = go.go,
    )

_gqlgen = _go_rule(
    implementation = _gqlgen_impl,
    attrs = {
        "config": attr.string(
            default = "gqlgen.yml",
            doc = "The gqlgen filename",
        ),
        "schemas": attr.label_list(
            allow_files = [".graphql"],
            doc = "The schema file location",
        ),
    },
    executable = True,
)

def gqlgen(**kwargs):
    tags = kwargs.get("tags", [])
    if "manual" not in tags:
        tags.append("manual")
        kwargs["tags"] = tags
    _gqlgen(**kwargs)

我的直接问题是 Bazel 抱怨模式不是 Files:

expected type 'File' for 'inputs' element but got type 'Target' instead

指定输入文件的正确方法是什么?

这是生成执行命令的规则的正确方法吗?

最后,输出文件不存在于文件系统中是否可以,而是作为其他规则可以依赖的标签?

而不是:

ctx.actions.run(
        inputs = ctx.attr.schemas,

使用:

ctx.actions.run(
        inputs = ctx.files.schemas,

Is this the right approach to generate a rule that executes a command?

这看起来是正确的,只要 gqlgen 使用正确的输出名称 (outputs = [ctx.actions.declare_file(ctx.attr.name)]) 创建文件。

generated_go_file = ctx.actions.declare_file(ctx.attr.name + ".go")

# ..

ctx.actions.run(
    outputs = [generated_go_file],
    args = ["run", "...", "--output", generated_go_file.short_path],
    # ..
)

Finally, is it okay to have the output file not exist in the filesystem, but rather be a label on which other rules can depend?

需要创建输出文件,只要在DefaultInfo provider中的规则执行结束时返回,其他规则就可以依赖于文件标签(例如//my/package:foo-gqlgen.go).