如何处理自定义Skylark规则

时间:2017-12-06 02:58:32

标签: bazel

问题

我想知道如何通知bazel关于在声明时未知的依赖关系,但在构建时知道(a.k.a隐式依赖关系,动态依赖关系......)。例如,在编译C ++源代码时,.cpp源文件将依赖于某些头文件,并且在编写BUILD文件时此信息不可用。它需要在构建时检索。无论获取信息的解决方案是什么(干运行,生成depfile,解析stdout),都需要在构建时完成,并且需要将信息检索到bazel构建图。

由于skylark不允许执行I / O,例如读取生成的depfile或解析包含依赖项列表的stdout结果,我不知道如何处理它。

在隐式依赖项后面,我正在寻找正确的增量构建。

实施例

为了试验这个问题,我创建了一个简单的工具just_a_tool.exe,它接受​​一个输入文件,从中读取文件列表,并将所有这些文件的内容连接到输出文件。

命令行示例:

just_a_tool.exe --input input.txt --depfile dep.d output.txt

dep.d包含所有读取文件的列表。

问题

如果我更改了test1.txt,test2.txt或test3.txt的内容,则bazel不会重建output.txt文件。当然,因为它不知道存在依赖性。

示例文件

just_a_tool.bzl

def _impl(ctx):
    exec_path = "C:/Code/JustATool/just_a_tool.exe"

    for f in ctx.attr.source.files:
        source_path = f.path
    output_path = ctx.outputs.out.path

    dep_file = ctx.actions.declare_file("dep.d")

    args = ["--input", source_path, "--dep_file", dep_file.path, output_path]

    ctx.actions.run(
        outputs=[ctx.outputs.out, dep_file], 
        executable=exec_path,
        inputs=ctx.attr.source.files,
        arguments=args
    )

jat_convert = rule(
    implementation = _impl,
    attrs = {
        "source" : attr.label(mandatory=True, allow_files=True, single_file=True)
    },
    outputs = {"out": "%{name}.txt"}
)

BUILD

load("//tool:just_a_tool.bzl", "jat_convert")

jat_convert(
    name="my_output",
    source=":input.txt"
)

input.txt中

test1.txt
test2.txt
test3.txt

目标

我希望针对以下情况进行正确且快速的增量构建:

  • 从C ++源生成反射数据,此自定义工具执行取决于源文件中包含的头文件。
  • 使用内部工具构建可包含其他文件的资产文件
  • 在我的着色器上运行自定义预处理器,允许使用#include功能

谢谢!

1 个答案:

答案 0 :(得分:0)

Bazel的扩展语言不支持使用动态输入集创建动作,其中此集取决于上一个动作的输出。换句话说,自定义规则无法运行操作,读取操作的输出,然后使用这些输入创建操作或更新(或修剪已设置的)已创建操作的输入。

相反,我建议在您的规则中添加属性,用户可以在其中声明源可能包含的文件集。我把它称为“标题的宇宙”。您创建的操作取决于此用户定义的Universe,因此完全定义了操作输入集。当然,这意味着这些操作可能依赖于比他们处理的cpp文件更多的文件,包括。

此方法类似于cc_*规则的工作方式:cc_*.srcs中的文件可以包含同一规则的srcs中的其他文件以及hdrs个依赖项中的文件, 但没有别的。因此,srcs + hdrs(直接和传递)依赖关系的并集定义了cpp文件可能包含的头文件的范围。