如何使Bazel Genrule访问传递依赖性?

发布于 2025-01-29 03:20:12 字数 1237 浏览 0 评论 0原文

我在build文件中有以下内容:

proto_library(
    name = "proto_default_library",
    srcs = glob(["*.proto"]),
    visibility = ["//visibility:public"],
    deps = [
        "@go_googleapis//google/api:annotations_proto",
        "@grpc_ecosystem_grpc_gateway//protoc-gen-openapiv2/options:options_proto",
    ],
)

genrule(
    name = "generate-buf-image",
    srcs = [
        ":buf_yaml",
        ":buf_breaking_image_json",
        ":protos",
    ],
    exec_tools = [
        ":proto_default_library",
        "//buf:generate-buf-image-sh",
        "//buf:generate-buf-image",
    ],
    outs = ["buf-image.json"],
    cmd = "$(location //buf:generate-buf-image-sh) --buf-breaking-image-json=$(location :buf_breaking_image_json) $(location :protos) >$@",
)

执行$(位置// buf:generate-buf-image-sh)glob([[“*)。 proto“]) proto_default_library可以在沙盒中看到,但是@go_googleapis // good>@go_googleapis // google/api:annotations_proto@grpc_ecosystem_grpc_gatewayway // protoc-gen-openapiv2/options:options_proto不能。 // buf的依赖项也是如此:生成buf-image-sh

我是否需要明确列出所有传递依赖项,以便可以通过生成buf-image处理它们?有没有程序化的方法?

I have the following in a BUILD file:

proto_library(
    name = "proto_default_library",
    srcs = glob(["*.proto"]),
    visibility = ["//visibility:public"],
    deps = [
        "@go_googleapis//google/api:annotations_proto",
        "@grpc_ecosystem_grpc_gateway//protoc-gen-openapiv2/options:options_proto",
    ],
)

genrule(
    name = "generate-buf-image",
    srcs = [
        ":buf_yaml",
        ":buf_breaking_image_json",
        ":protos",
    ],
    exec_tools = [
        ":proto_default_library",
        "//buf:generate-buf-image-sh",
        "//buf:generate-buf-image",
    ],
    outs = ["buf-image.json"],
    cmd = "$(location //buf:generate-buf-image-sh) --buf-breaking-image-json=$(location :buf_breaking_image_json) $(location :protos) >$@",
)

While executing $(location //buf:generate-buf-image-sh), glob(["*.proto"]) of proto_default_library can be seen in the sandbox but the proto files of @go_googleapis//google/api:annotations_proto and @grpc_ecosystem_grpc_gateway//protoc-gen-openapiv2/options:options_proto cannot. The same goes for the dependencies of //buf:generate-buf-image-sh.

Do I need to explicitly list out all transitive dependencies so they can be processed by generate-buf-image? Is there a programmatic way to do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深海蓝天 2025-02-05 03:20:12

由于Genrules非常通用,因此Genrule仅看到目标的默认提供商,该提供商通常只有该目标的主要输出(例如,对于Java_library,该库中的一罐该库,对于Proto_library,对于proto_library来说图书馆)。因此,要获取更详细的信息,您将编写一项Starlark规则以访问更多特定的提供商。例如:

workspace

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_proto",
    sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
    strip_prefix = "rules_proto-4.0.0",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
        "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
    ],
)
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()

defs.bzl

def _my_rule_impl(ctx):
  output = ctx.actions.declare_file(ctx.attr.name + ".txt") 
  args = ctx.actions.args()
  args.add(output)
  inputs = []
  for src in ctx.attr.srcs:
    proto_files = src[ProtoInfo].transitive_sources
    args.add_all(proto_files)
    inputs.append(proto_files)

  ctx.actions.run(
    inputs = depset(transitive = inputs),
    executable = ctx.attr._tool.files_to_run,
    arguments = [args],
    outputs = [output],
  )
  return DefaultInfo(files = depset([output]))

my_rule = rule(
  implementation = _my_rule_impl,
  attrs = {
    "srcs": attr.label_list(providers=[ProtoInfo]),
    "_tool": attr.label(default = "//:tool"),
  },
)

protoinfo在这里: https://bazel.build/rules/lib/lib/protoinfo

构建

load(":defs.bzl", "my_rule")

proto_library(
  name = "proto_a",
  srcs = ["proto_a.proto"],
  deps = [":proto_b"],
)

proto_library(
  name = "proto_b",
  srcs = ["proto_b.proto"],
  deps = [":proto_c"],
)

proto_library(
  name = "proto_c",
  srcs = ["proto_c.proto"],
)

my_rule(
  name = "foo",
  srcs = [":proto_a"],
)

sh_binary(
  name = "tool",
  srcs = ["tool.sh"],
)

proto_a.a.proto :

package my_protos_a;

message ProtoA {
  optional int32 a = 1;
}

proto_b.proto

package my_protos_b;

message ProtoB {
  optional int32 b = 1;
}

proto_c.proto

package my_protos_c;

message ProtoC {
  optional int32 c = 1;
}

tool.sh

output=$1
shift

echo input protos: $@ > $output
$ bazel build foo
INFO: Analyzed target //:foo (40 packages loaded, 172 targets configured).
INFO: Found 1 target...
Target //:foo up-to-date:
  bazel-bin/foo.txt
INFO: Elapsed time: 0.832s, Critical Path: 0.02s
INFO: 5 processes: 4 internal, 1 linux-sandbox.
INFO: Build completed successfully, 5 total actions

$ cat bazel-bin/foo.txt
input protos: proto_a.proto proto_b.proto proto_c.proto

Since genrules are pretty generic, a genrule sees only the default provider of a target, which usually just has the main outputs of that target (e.g., for java_library, a jar of the classes of that library, for proto_library, the proto files of that library). So to get more detailed information, you would write a Starlark rule to access more specific providers. For example:

WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "rules_proto",
    sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
    strip_prefix = "rules_proto-4.0.0",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
        "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
    ],
)
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()

defs.bzl:

def _my_rule_impl(ctx):
  output = ctx.actions.declare_file(ctx.attr.name + ".txt") 
  args = ctx.actions.args()
  args.add(output)
  inputs = []
  for src in ctx.attr.srcs:
    proto_files = src[ProtoInfo].transitive_sources
    args.add_all(proto_files)
    inputs.append(proto_files)

  ctx.actions.run(
    inputs = depset(transitive = inputs),
    executable = ctx.attr._tool.files_to_run,
    arguments = [args],
    outputs = [output],
  )
  return DefaultInfo(files = depset([output]))

my_rule = rule(
  implementation = _my_rule_impl,
  attrs = {
    "srcs": attr.label_list(providers=[ProtoInfo]),
    "_tool": attr.label(default = "//:tool"),
  },
)

ProtoInfo is here: https://bazel.build/rules/lib/ProtoInfo

BUILD:

load(":defs.bzl", "my_rule")

proto_library(
  name = "proto_a",
  srcs = ["proto_a.proto"],
  deps = [":proto_b"],
)

proto_library(
  name = "proto_b",
  srcs = ["proto_b.proto"],
  deps = [":proto_c"],
)

proto_library(
  name = "proto_c",
  srcs = ["proto_c.proto"],
)

my_rule(
  name = "foo",
  srcs = [":proto_a"],
)

sh_binary(
  name = "tool",
  srcs = ["tool.sh"],
)

proto_a.proto:

package my_protos_a;

message ProtoA {
  optional int32 a = 1;
}

proto_b.proto:

package my_protos_b;

message ProtoB {
  optional int32 b = 1;
}

proto_c.proto:

package my_protos_c;

message ProtoC {
  optional int32 c = 1;
}

tool.sh:

output=$1
shift

echo input protos: $@ > $output
$ bazel build foo
INFO: Analyzed target //:foo (40 packages loaded, 172 targets configured).
INFO: Found 1 target...
Target //:foo up-to-date:
  bazel-bin/foo.txt
INFO: Elapsed time: 0.832s, Critical Path: 0.02s
INFO: 5 processes: 4 internal, 1 linux-sandbox.
INFO: Build completed successfully, 5 total actions

$ cat bazel-bin/foo.txt
input protos: proto_a.proto proto_b.proto proto_c.proto
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文