You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确依赖外部仓库proto_library规则并使用自定义规则生成nanopb文件?

解决Bazel自定义Nanopb规则访问外部仓库.proto文件的问题

我刚好碰到过类似的场景,核心问题是Bazel的proto_library默认不会直接暴露原始的.proto源文件给自定义规则,你需要通过Bazel内置的ProtoInfo提供者来提取这些文件。下面是具体的实现方案:

关键思路:利用ProtoInfo获取源文件

Bazel为所有proto_library目标提供了ProtoInfo这个信息提供者,它包含了该proto库的所有源文件路径、导入路径等关键数据。自定义规则可以通过访问这个提供者,拿到外部仓库的底层.proto文件。

自定义规则示例

# 导入ProtoInfo定义
load("@rules_proto//proto:defs.bzl", "ProtoInfo")

def _nanopb_generator_impl(ctx):
    # 从依赖的proto_library中获取ProtoInfo
    proto_info = ctx.attr.proto_target[ProtoInfo]
    
    # 提取直接关联的.proto源文件(包括外部仓库的)
    direct_proto_files = proto_info.direct_sources
    
    # 构造protoc命令参数:指定nanopb输出目录、proto搜索路径,以及源文件
    protoc_command_args = [
        "--nanopb_out=" + ctx.outputs.gen_dir.path,
        # 添加所有必要的proto导入路径
    ] + ["--proto_path=" + path for path in proto_info.transitive_import_path.to_list()] + [src.path for src in direct_proto_files]
    
    # 执行protoc生成nanopb代码
    ctx.actions.run(
        executable = ctx.executable.protoc,
        arguments = protoc_command_args,
        # 传递所有依赖的proto文件作为输入,确保Bazel能追踪依赖
        inputs = depset(direct_proto_files, transitive = [proto_info.transitive_sources]),
        outputs = [ctx.outputs.gen_dir],
    )

# 定义自定义规则
nanopb_generate = rule(
    implementation = _nanopb_generator_impl,
    attrs = {
        # 接收一个proto_library目标作为输入
        "proto_target": attr.label(providers = [ProtoInfo]),
        # 指定protoc工具,默认用Bazel官方的protobuf工具链
        "protoc": attr.label(
            executable = True,
            cfg = "exec",
            default = Label("@com_google_protobuf//:protoc"),
        ),
    },
    # 这里可以根据需要定义输出,比如生成.h和.c文件
    outputs = {
        "gen_dir": "%{name}_gen",
    },
)

使用方式

在你的BUILD文件里直接引用外部仓库的proto_library即可:

nanopb_generate(
    name = "awesome_nanopb_gen",
    proto_target = "@other_repo//proto:awesome_proto",
)

注意事项

  • 导入路径设置:一定要把proto_info.transitive_import_path里的路径添加到--proto_path参数中,否则protoc可能找不到外部仓库proto文件里的导入依赖。
  • 依赖追踪:用depset把transitive_sources包含到输入里,这样Bazel能正确处理跨仓库的依赖关系,当外部仓库的proto文件更新时,你的自定义规则会自动重新生成代码。
  • Nanopb选项:如果需要设置Nanopb的自定义选项(比如生成结构体的方式、字段处理),可以在--nanopb_out后面添加参数,比如--nanopb_out=enable_struct_names:%{name}_gen。

内容的提问来源于stack exchange,提问作者user1483946

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:37:12