如何基于目录动态生成Bazel规则的Deps依赖
在Bazel中动态生成插件依赖的解决方案
针对你遇到的问题——无法通过glob获取子目录的Bazel目标作为依赖,以下是两种可行的实现方案:
方案一:约定子包目标名称(简单易实现)
核心思路是通过subpackages()函数获取当前包下的所有子包,再构造对应的目标标签,避免硬编码。
步骤1:根目录BUILD文件(//plugins_folder/BUILD)
# 获取当前包下的所有子包(返回["plugin1", "plugin2"]) PLUGIN_SUBPACKAGES = subpackages() # 构造子包的目标引用,假设每个子包BUILD中都有一个名为`plugin`的py_library目标 PLUGIN_DEPS = ["//plugins_folder/{}:plugin".format(pkg) for pkg in PLUGIN_SUBPACKAGES] py_library( name = "code0", srcs = ["code0.py"], deps = PLUGIN_DEPS, )
步骤2:子包BUILD文件(如//plugins_folder/plugin1/BUILD)
每个子包统一输出名为plugin的py_library目标:
py_library( name = "plugin", srcs = glob(["*.py"]), )
方案二:使用Aspect自动收集目标(灵活适配复杂场景)
如果子包的目标名称不固定,可通过Bazel的Aspect机制自动扫描并收集所有py_library目标。
步骤1:定义Aspect规则(//plugins_folder/plugins.bzl)
def _collect_plugins_aspect_impl(target, ctx): # 收集当前目标的py_library引用 deps = [] if ctx.rule.kind == "py_library": deps.append(target) # 递归收集依赖链中的py_library目标 for dep in ctx.rule.attr.deps: deps.extend(dep[PluginAspect].plugin_deps) return struct(plugin_deps = deps) PluginAspect = aspect( implementation = _collect_plugins_aspect_impl, attr_aspects = ["deps"], ) def _dynamic_plugin_deps_impl(ctx): all_deps = [] for dep in ctx.attr.plugins: all_deps.extend(dep[PluginAspect].plugin_deps) return struct(deps = all_deps) dynamic_plugin_deps = rule( implementation = _dynamic_plugin_deps_impl, attrs = {"plugins": attr.label_list(aspects = [PluginAspect])}, )
步骤2:根目录BUILD文件(//plugins_folder/BUILD)
load(":plugins.bzl", "dynamic_plugin_deps") # 获取所有子包的全量目标 PLUGIN_PACKAGES = ["//plugins_folder/{}:all".format(pkg) for pkg in subpackages()] # 动态收集所有子包中的py_library目标 dynamic_plugin_deps( name = "plugin_deps", plugins = PLUGIN_PACKAGES, ) py_library( name = "code0", srcs = ["code0.py"], deps = [":plugin_deps"], )
为什么glob无法解决问题?
glob()仅能匹配文件系统中的文件路径,而Bazel的deps需要的是目标标签(如//plugin1:code1-0),这些标签由子包的BUILD文件定义,不属于文件系统的直接文件,因此glob无法直接获取。
内容的提问来源于stack exchange,提问作者Ran Silberman
相关产品推荐
相关产品推荐

