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

子文件夹py_library目标对自定义Bazel构建规则不可见问题求助

问题分析与解决方案

核心问题原因

你遇到的问题有两个关键原因:

  1. Glob模式错误:你的pattern = ["**/.*py"]是匹配以.py开头的隐藏文件(比如.pyfile.py),而非所有Python源文件,正确的模式应该是**/*.py。
  2. Bazel Glob默认行为:native.glob默认会跳过包含BUILD文件的子目录(exclude_directories=True是默认值),这就是为什么删除子目录BUILD文件后,glob能正常遍历到里面的文件——此时该目录不再被Bazel视为包目录,会被当作普通目录处理。

修正后的基础实现

先修正glob的参数,让它能正确遍历所有子目录的Python文件:

def compute_deps():
    # 修正模式为匹配所有py文件,允许遍历含BUILD的子目录
    pattern = ["**/*.py"]
    all_files = native.glob(pattern, exclude_directories=False)
    print(all_files)
    deps = [convert_path_to_target(filepath) for filepath in all_files]
    return deps

def custom_build_rule(name, main, srcs):
    deps = compute_deps()
    return py_binary(
        name = name,
        main = main,
        srcs = srcs,
        deps = deps
    )

更可靠的实现思路

不过上面的方法仍有隐患:你是通过Python文件路径推导目标标签,但子目录中的py_library目标名不一定和文件名对应(比如子目录BUILD中可能定义py_library(name="utils", srcs=["helper.py"])),直接关联文件会导致依赖错误。

更合理的方式是直接引用子目录的py_library目标,而非文件:

def compute_deps():
    # 获取所有子目录(匹配subdir1-subdir5这类目录)
    subdirs = native.glob(["subdir*/"], exclude_directories=False)
    # 用`:all`引用该目录下所有public目标(符合你子目录BUILD的default_visibility设置)
    # 若每个子目录的py_library名字固定(比如和目录名一致),可改为f"//src/{dir.rstrip('/')}:{dir.rstrip('/')}"
    deps = [f"//src/{dir.rstrip('/')}:all" for dir in subdirs]
    return deps

def custom_build_rule(name, main, srcs):
    deps = compute_deps()
    return py_binary(
        name = name,
        main = main,
        srcs = srcs,
        deps = deps
    )

:all是Bazel的特殊标签,会引用对应包下所有default_visibility为public的目标,刚好适配你的项目设置。

为什么bazel query能查到所有目标?

bazel query //my/project/...会遍历所有包目录(含BUILD文件的目录)并列出其中的目标,它的遍历逻辑和native.glob不同,不受exclude_directories参数影响,所以能正常查到所有子目录的py_library。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:58:28