如何调试Bazel分析阶段并解决pkg_tar的remap_paths失效问题?
我使用Bazel 3.4和rules_pkg 0.3,手里有一组带多级目录的.so文件,每个子目录对应特定架构的.so文件,现在要把这些文件打包分发。希望去掉架构目录层级,让最终的pkg.tar少一层目录结构(这样加载器更容易指向.so文件)。但因为用的是rules_pkg 0.3,没法用pkg_files。
我写了下面的规则,但remap_paths完全不起作用,输出的tar包里还是有lib/arm64、lib/amd64目录。是不是哪里漏了?
我已经做了这些步骤:
- 用
bazel build --subcommands target查看tar_pkgs动作阶段的参数文件,确认remap没应用到参数文件里,问题肯定出在分析阶段。 - 尝试调试分析阶段,在本地缓存目录
~/.cache/sandox_hash/external/rules_pkg/pkg.bzl里加打印语句,但没效果。就算在pkg.bzl里写语法错误的Python代码,构建也不受影响,好像这个文件没被重新解析。
另外想问下,有哪些工具可以用来打印/调试分析阶段?
对应的规则代码:
pkg_tar( name = "my_tar", srcs = select({ "//condition_here" : ["lib/arm64"] "//conditions:default" : ["lib/amd64"] }), remap_paths = { "lib/amd64" : "lib", "lib/arm64" : "lib", }, mode = "0644", package_dir = "/package/dir", visibility = ["//visibility:public"], )
一、remap_paths失效的原因与修复
rules_pkg 0.3的remap_paths是基于文件的原始路径而非目录路径来匹配的,你在srcs里传入的是整个目录(lib/arm64、lib/amd64),规则会把目录本身作为源处理,remap逻辑无法穿透目录匹配到内部的.so文件。
你需要把srcs改成目录下的具体文件,用glob匹配所有.so文件,这样remap才能逐个处理文件路径:
pkg_tar( name = "my_tar", srcs = select({ "//condition_here": glob(["lib/arm64/*.so"]), "//conditions:default": glob(["lib/amd64/*.so"]) }), remap_paths = { "lib/amd64": "lib", "lib/arm64": "lib", }, mode = "0644", package_dir = "/package/dir", visibility = ["//visibility:public"], )
另外注意,rules_pkg 0.3的remap_paths是前缀匹配,确保键是文件路径的准确前缀,比如lib/arm64/libfoo.so会被替换成lib/libfoo.so。
二、分析阶段调试工具与方法
1. Bazel内置调试参数
- 生成分析阶段日志:执行
bazel build --verbose_failures --subcommands --explain=analysis.log target,analysis.log会记录分析阶段的详细决策,包括规则属性的处理逻辑。 - 直接打印属性值:在BUILD文件里用
print()输出属性内容,比如:
执行selected_srcs = select({ "//condition_here": glob(["lib/arm64/*.so"]), "//conditions:default": glob(["lib/amd64/*.so"]) }) print("Selected srcs:", selected_srcs) pkg_tar( name = "my_tar", srcs = selected_srcs, # 其他属性... )bazel build target时,控制台会直接输出打印内容。
2. 正确修改rules_pkg源码调试
你修改缓存里的pkg.bzl没生效,是因为Bazel会缓存外部依赖的源码。要让修改生效:
- 在
WORKSPACE里把rules_pkg改成本地依赖:local_repository( name = "rules_pkg", path = "/path/to/your/local/rules_pkg", ) - 修改本地
rules_pkg/pkg.bzl后,执行bazel clean --expunge清除缓存,再重新构建,修改的代码才会被解析。
3. 用bazel query验证配置
执行bazel query --output=build //path/to:my_tar,查看目标的实际构建配置,确认remap_paths和srcs是否被正确解析。
内容的提问来源于stack exchange,提问作者Dragonsheep

