Bazel构建时生成未知数量文件的问题及解决方案咨询
问题分析与解决方案
核心问题判断
你当前的方案确实注定失败。Bazel的构建依赖模型要求所有输入、输出必须在分析阶段(加载BUILD文件时)明确声明,你直接在cc_library的srcs里引用source/Generated/*时,Bazel会在genrule执行前就扫描这个路径——如果第一次构建时该路径为空,Bazel会认定没有这些源文件,后续genrule生成文件后也不会重新触发扫描;即使路径已有文件,Bazel也不会把它们和genrule的执行关联,完全无法保证依赖顺序。
另外,genrule的占位文件trick本质是绕过Bazel的依赖检查,这种做法本身就不符合Bazel的设计原则,必然会导致构建不稳定。
可行解决方案
1. 自定义Bazel规则(推荐用于正式构建)
这是处理“动态数量输出文件”场景的标准方案,比如SWIG绑定生成这类需求,社区里也有成熟的实践:
- 编写一个自定义规则(比如
swig_bindings),在规则的实现逻辑中:- 执行SWIG命令生成绑定代码;
- 通过扫描输出目录、解析SWIG日志或命令输出的方式,收集所有生成的
.cpp/.java文件; - 将这些文件标记为规则的输出,传递给后续的
cc_library/java_library。
- 若需要将生成文件放到项目目录用于调试,可以在规则中添加可选属性(比如
output_to_workspace),在本地构建时将生成文件从Bazel缓存目录复制/软链到源码目录,但要注意:- 给生成目录添加
.gitignore,避免提交自动生成的文件; - 正式构建时关闭该属性,使用Bazel缓存的文件保证构建一致性。
- 给生成目录添加
- 自定义规则可以设置
local = True,强制在本地执行(而非沙箱),满足你调试时的路径需求。
2. 临时调试用的折中方案
如果不想写自定义规则,仅用于本地调试,可以调整genrule的写法:
- 修改genrule的
cmd,确保生成所有文件后再创建占位文件:genrule( name = "generate_files", srcs = ["generator.sh"], outs = ["generated_placeholder"], cmd = "./$(location generator.sh) && touch $@", local = True, ) - 在
cc_library中,将占位文件作为data依赖,同时用glob引用生成文件:cc_library( name = "my_lib", srcs = glob(["source/Generated/*"]) + [":generate_files"], data = [":generate_files"], ) - 注意:这个方案仅能用于临时调试,因为Bazel在分析阶段会缓存
glob的结果,后续生成新文件时需要手动清理Bazel缓存(bazel clean)才能重新扫描,完全不适合正式构建或CI环境。
3. 社区现成规则参考
很多开发者都遇到过类似的SWIG绑定生成问题,社区有现成的规则集可以直接使用,这些规则已经处理了动态输出文件、多语言绑定、依赖顺序等问题,无需自己从零实现。
内容的提问来源于stack exchange,提问作者AnDevi
相关产品推荐
相关产品推荐

