如何修改Bazel构建输出目录的存放位置
使用--output_base=$PWD/output或--output_user_root=$PWD/output参数构建报错的核心原因是Bazel的强制设计限制:所有输出根路径不能位于包含WORKSPACE文件的当前工作区目录树内。如果把输出目录放在工作区内部,Bazel执行源码扫描、沙箱挂载、增量构建校验时会出现路径循环、文件重复扫描、权限冲突等随机错误,和你遇到的现象完全一致。
另外你看到的bazel-bin、bazel-out等软链是Bazel生成的便捷入口,本身不是产物实际存储位置,默认指向用户目录下.cache缓存路径是Bazel的默认行为。
根据你的需求(构建产物实际存放在当前工作区,不依赖.cache目录的软链),有两种无报错的实现方式:
方案1:构建后自动拷贝产物到工作区(最推荐,无兼容性问题)
不改动Bazel原生的缓存、增量构建逻辑,完全避免参数配置带来的报错,构建完成后直接跟随软链拷贝实际文件到工作区本地目录即可:
- 执行以下命令完成构建+产物导出:
# 正常执行构建,不会有任何报错 bazel build //... # 在工作区创建本地产物目录,-L参数会跟随软链拷贝实际文件,不保留软链 mkdir -p ./build_output cp -rL ./bazel-bin/* ./build_output/ cp -rL ./bazel-testlogs/* ./build_output/testlogs/
执行完成后,./build_output目录下就是实打实存储在当前工作区的构建产物,完全脱离对.cache目录的依赖,删除.cache目录也不会影响这个目录下的文件。
如果需要固定导出流程,可以在项目里写简单的Makefile或者bash脚本封装上述命令,不需要修改任何Bazel配置。
方案2:修改全局输出路径到工作区外,调整软链指向
如果你不想使用用户根目录下的默认.cache路径,要把所有构建缓存、产物放到和项目关联的路径,注意输出目录必须放在工作区的平级或者上级位置,绝对不能放在工作区目录内部:
- 正确的参数使用示例(假设你的项目路径为
/home/bkch/distroless,WORKSPACE文件就在该目录下):
# 输出目录放在项目平级位置,和WORKSPACE所在目录不嵌套 bazel --output_base=/home/bkch/bazel_distroless_cache build //...
执行完成后,项目下的bazel-bin、bazel-out等软链会自动指向你指定的平级缓存目录,不会再链接到~/.cache路径下的内容。
注意:不要使用
/home/bkch/distroless/output这类嵌套在工作区内部的路径作为output_base或output_user_root,否则必然触发之前的各类随机报错。
Bazel原生不支持完全取消软链、直接把构建产物输出到工作区源码树的模式,这个设计是为了做源码和构建产物的隔离:避免构建动作意外覆盖源码文件,同时保证增量构建的文件扫描效率,强行突破这个限制会导致构建速度下降、缓存失效等问题,不建议尝试。
内容的提问来源于stack exchange,提问作者BhanuKiran

