子文件夹py_library目标对自定义Bazel构建规则不可见问题求助
问题分析与解决方案
核心问题原因
你遇到的问题有两个关键原因:
- Glob模式错误:你的
pattern = ["**/.*py"]是匹配以.py开头的隐藏文件(比如.pyfile.py),而非所有Python源文件,正确的模式应该是**/*.py。 - 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
相关产品推荐
相关产品推荐

