在一个 bazel 规则中链接 expand_template 和 运行

Chain expand_template and run in one bazel rule

我正在尝试编写一个自定义规则,我首先从模板生成一个文件,然后将该文件传递给脚本以生成一些 c++ headers 作为我的规则的输出。

def _msg_library_impl(ctx):
  # For each target in deps, print its label and files.
  for source in enumerate(ctx.attr.srcs):
    print("File = " + str(source))
  out_header = ctx.actions.declare_file("some_header.hpp")
  out_arguments = ctx.actions.declare_file("arguments.json")
  ctx.actions.expand_template(
        template = ctx.file._arguments_file,
        output = out_arguments,
        substitutions = {
            "{output_dir}": out_header.dirname,
            "{idl_tuples}": out_header.path,
        },
  )
  args = ctx.actions.args()
  args.add("--arguments-file")
  args.add(out_arguments)
  ctx.actions.run(
      outputs = [out_header],
      progress_message = "Generating headers '{}'".format(out_header.short_path),
      executable = ctx.executable._generator,
      arguments = [args],
  )
  return [
    CcInfo(compilation_context=cc_common.create_compilation_context(
        includes=depset([out_header.dirname]),
        headers=depset([out_header])))
  ]



msg_library = rule(
    implementation = _msg_library_impl,
    output_to_genfiles = True,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        "outs": attr.output_list(),
        "_arguments_file": attr.label(
            allow_single_file = [".json"],
            default = Label("//examples/generation_rule:arguments_template.json"),
        ),
        "_generator": attr.label(
            default = Label("//examples/generation_rule:generator"),
            executable = True,
            cfg = "exec"
        ),
    },
)

这里,generator 是一个 python 库,给定一个提供给 srcs 的输入文件和一个参数文件生成 headers.

我面临的问题是,似乎 expand_templaterun 被调用之前实际上并没有 运行,因此找不到生成的文件。我在这里做错了什么?我是不是误解了事情的运作方式?

除了在参数中传递其路径之外,您还需要指明该文件是操作的输入。将 ctx.actions.run 更改为:

  ctx.actions.run(
      outputs = [out_header],
      inputs = [out_arguments],
      progress_message = "Generating headers '{}'".format(out_header.short_path),
      executable = ctx.executable._generator,
      arguments = [args],
  )