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

如何在Bazel规则运行时获取指定目录下的自动生成文件

在Bazel中获取生成文件并转换为ProtoInfo的解决方案

核心问题说明

你尝试基于openapi-generator-bazel的规则生成文件后,将DefaultInfo转换为ProtoInfo,但直接用ctx.glob()扫描输出目录不可行——因为ctx.glob()运行在Bazel的分析阶段,此时生成文件还未在执行阶段产生,无法直接获取。

可行解决方案

1. 利用TreeArtifact扫描生成文件

openapi-generator-bazel返回的declared_dir是一个TreeArtifact(目录类型输出),必须通过执行阶段的动作来遍历其中的.proto文件:

def _openapi_proto_wrapper_impl(ctx):
    # 从依赖中获取DefaultInfo和输出目录
    openapi_default = ctx.attr.dep[DefaultInfo]
    output_dir = openapi_default.files.to_list()[0]

    # 声明一个临时文件,用于存储扫描到的.proto文件路径
    proto_list_file = ctx.actions.declare_file(f"{ctx.label.name}_protos.txt")
    
    # 执行shell命令扫描目录下的.proto文件并写入临时文件
    ctx.actions.run_shell(
        inputs = [output_dir],
        outputs = [proto_list_file],
        command = f"find {output_dir.path} -type f -name '*.proto' > {proto_list_file.path}",
    )

    # 读取临时文件中的路径,转换为Bazel File对象
    proto_files = []
    for line in proto_list_file.readlines():
        proto_path = line.strip()
        # 通过output_dir的路径关联找到对应的File对象
        proto_file = ctx.actions.declare_file(proto_path[len(output_dir.path)+1:], sibling=output_dir)
        proto_files.append(proto_file)

2. 构建ProtoInfo结构

使用Bazel的proto_common模块创建ProtoInfo,确保传入正确的源码和根目录:

# 导入proto_common模块(需在BUILD文件中依赖相关规则)
    proto_info = proto_common.create_proto_info(
        ctx,
        direct_sources = proto_files,
        proto_source_root = output_dir.path,
        transitive_sources = depset(proto_files),
    )

    # 返回组合后的信息
    return [
        openapi_default,
        proto_info,
    ]

3. 更优方案:直接声明生成文件

如果openapi-generator-bazel支持配置生成的.proto文件名,建议直接在规则中声明这些文件,避免执行阶段扫描:

# 在自定义规则中添加属性让用户指定生成的proto文件名
attrs = {
    "dep": attr.label(mandatory=True, providers=[DefaultInfo]),
    "proto_file_names": attr.string_list(mandatory=True),
}

# 在实现中直接声明文件
proto_files = [ctx.actions.declare_file(f, sibling=output_dir) for f in ctx.attr.proto_file_names]

关键注意事项

  • 阶段分离:严格区分Bazel的分析阶段和执行阶段,分析阶段无法获取执行阶段生成的文件,必须通过动作中转。
  • TreeArtifact处理:TreeArtifact仅代表目录本身,需通过执行动作遍历子文件,或通过声明的关联文件获取具体生成的.proto。
  • ProtoInfo参数:proto_source_root必须设置为生成文件所在的根目录,确保Protobuf工具能正确解析导入路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:23:18