如何在Bazel动作中生成配置文件并与源文件同目录放置?
自定义Bazel规则适配foo-compiler的路径问题
问题背景
我正在为foo-compiler编写自定义Bazel规则foo_library,用户通过如下方式传入源文件:
foo_library( name = "hello", srcs = [ "A.foo", "B.foo" ], )
非Bazel环境下的构建流程是:
- 生成包含源文件列表的
config.json:
{ "srcs": [ "./A.foo", "./B.foo" ] }
- 将
config.json放在源文件同目录下:
$ ls . A.foo B.foo config.json
- 在该目录执行编译命令:
$ foo-compiler .
目前Bazel规则实现中,已成功生成内容正确的config.json,但无法将其放置到源文件所在目录:
config_file = ctx.actions.declare_file("config.json") ctx.actions.write( output = config_file, content = json_for_srcs(ctx.files.srcs), )
需要解决:如何让Bazel将config.json放到源文件所在目录?或者是否需要复制源文件到配置文件旁?
解决方案
1. 理解Bazel的路径限制
Bazel的构建沙盒机制会严格隔离源文件目录和生成文件输出目录,生成的文件(如config.json)只能写入Bazel管理的输出目录,无法直接放到源文件所在的目录。强行操作会破坏增量构建和缓存逻辑,违背Bazel的设计原则。
2. 两种可行适配方案
方案一:修改配置文件路径为绝对路径,直接指定配置文件编译
无需将config.json与源文件放在同一目录,而是生成配置文件时写入源文件的绝对路径:
def json_for_srcs(srcs): src_paths = [src.path for src in srcs] return json.encode({"srcs": src_paths})
调用foo-compiler时直接传入配置文件路径,而非目录:
ctx.actions.run( inputs = ctx.files.srcs + [config_file], outputs = [ctx.outputs.library], # 替换为你的实际输出文件 arguments = [config_file.path], executable = "foo-compiler", )
如果foo-compiler不支持直接传入配置文件路径,可以编写一个简单的包装脚本,读取指定路径的配置文件后执行编译逻辑。
方案二:复制源文件与配置文件到临时目录编译
如果foo-compiler强制要求配置文件与源文件同目录,可以在构建动作中创建临时目录,复制所有文件后执行编译:
# 声明临时构建目录作为输出 temp_dir = ctx.actions.declare_directory("temp_build_dir") ctx.actions.run_shell( inputs = ctx.files.srcs + [config_file], outputs = [temp_dir, ctx.outputs.library], command = """ mkdir -p {temp_dir} # 复制所有源文件到临时目录 for src in {srcs}; do cp "$src" "{temp_dir}/" done # 复制配置文件 cp "{config_file}" "{temp_dir}/config.json" # 在临时目录执行编译 foo-compiler "{temp_dir}" # 将编译产物复制到Bazel指定的输出位置 cp "{temp_dir}/your_output_file" "{output}" """.format( temp_dir = temp_dir.path, srcs = " ".join([shlex.quote(src.path) for src in ctx.files.srcs]), config_file = config_file.path, output = ctx.outputs.library.path, ), )
注意:使用declare_directory需要Bazel版本支持,且要确保正确提取编译产物,让Bazel能追踪输出文件的变化。
3. 方案优先级
优先选择方案一,它更符合Bazel的设计理念,无需额外复制操作,构建效率更高,能更好地利用Bazel的缓存机制。仅当foo-compiler完全无法修改路径处理逻辑时,再考虑方案二。
内容的提问来源于stack exchange,提问作者sdgfsdh
相关产品推荐
相关产品推荐

