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

如何通过命令行参数实现Bazel规则生成filegroup并依赖动态目标

Bazel动态创建依赖命令行指定路径的filegroup

我需要实现:执行Bazel构建命令时传入一个路径(或目录名),将该路径下所有文件纳入一个filegroup,作为其他目标的依赖。指定目录下已存在BUILD.bazel文件,但折腾一整天仍未解决。

我尝试的代码如下:

def _impl(ctx):
    my_setting_value = ctx.build_setting_value
    all_files = native.glob(["<path to>/" + my_setting_value + "/**"])

    ctx.actions.declare_file_group(
        name = ctx.label.name + "_group",
        srcs = all_files,
    )

custom_filegroup = rule(
    implementation = _impl,
    build_setting = config.string(flag = True),

    outputs = {
        "my_custom_filegroup": "%{name}_group",
    },
)

随后在BUILD文件中定义目标:

custom_filegroup(name = "my_files", build_setting_default="")

并将":my_files.my_custom_filegroup"作为依赖添加到另一目标。执行bazel build //<path to>:my_files时,持续收到错误:

"glob错误:'native.glob'只能在加载阶段调用"


问题根源

native.glob是Bazel加载阶段的API,仅能在BUILD文件、宏或扩展的加载阶段调用,不能用于规则的实现函数(属于分析/执行阶段)。规则实现阶段必须使用Bazel提供的阶段安全API来获取文件。

正确实现方案

1. 定义自定义规则与构建设置

在.bzl扩展文件或BUILD文件中编写:

load("@bazel_skylib//lib:paths.bzl", "paths")

def _custom_filegroup_impl(ctx):
    target_path = ctx.build_setting_value
    if not target_path:
        fail("必须通过命令行传入路径,示例:--//<path to>:my_files=<目标路径>")
    
    # 基于当前包目录拼接完整路径
    full_path = paths.join(ctx.label.package, target_path)
    
    # 使用ctx.glob获取文件(执行阶段安全API)
    all_files = ctx.glob([full_path + "/**"])
    
    # 声明文件组并通过提供者暴露
    file_group = ctx.actions.declare_file_group(
        name = ctx.label.name + "_files",
        srcs = all_files,
    )
    
    return [
        DefaultInfo(files = depset(all_files)),
        OutputGroupInfo(my_custom_filegroup = file_group),
    ]

custom_filegroup = rule(
    implementation = _custom_filegroup_impl,
    build_setting = config.string(flag = True),
    provides = [OutputGroupInfo],
)

2. 在BUILD文件中定义目标与依赖

custom_filegroup(name = "my_files", build_setting_default="")

# 示例依赖目标(以cc_binary为例)
cc_binary(
    name = "my_binary",
    srcs = ["main.cc"],
    # 方式1:直接依赖规则,通过DefaultInfo获取所有文件
    data = [":my_files"],
    # 方式2:依赖指定输出组
    # data = [":my_files.my_custom_filegroup"],
)

3. 执行构建命令

bazel build //<path to>:my_binary --//<path to>:my_files=relative/path/to/dir

其中relative/path/to/dir是相对于当前包目录的路径,也可以使用以工作区根目录为基准的绝对路径。

额外说明

  • 若未引入@bazel_skylib,需在WORKSPACE文件中添加:
    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    
    http_archive(
        name = "bazel_skylib",
        sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d",
        urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.1/bazel-skylib-1.4.1.tar.gz"],
    )
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:02:23