如何从Bazel中的另一个规则中创建规则

Jos*_*art 5 bazel

情况

我有两个Skylark扩展规则:blah_libraryblah_binary。所有blah_library的传递依赖关系都通过返回传播,provider(transitive_deps=...)并由任何最终依赖blah_binary目标进行适当处理。

我想做的事

我希望每个blah_library人也创建一个filegroup具有上述所有传递性依赖项的,以便我可以分别访问它们。例如,我希望能够将它们作为数据依赖项传递给cc_binary。换一种说法:

# Somehow have this automatically create a target named `foo__trans_deps`?
blah_library(
    name = "foo",
    srcs = [...],
    deps = [...],
)

cc_binary(
    ...,
    data = [":foo__trans_deps"],
)
Run Code Online (Sandbox Code Playgroud)

我应该怎么做?任何帮助,将不胜感激!

我尝试过的

制作宏

我试图像这样制作一个宏:

_real_blah_library = rule(...)

def blah_library(name, *args, **kwargs):
    native.filegroup(
        name = name + "__trans_deps",
        srcs = ???,
    )
    _real_blah_library(name=name, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

但是我不确定如何从宏中访问providerby _real_blah_library,因此我不知道如何填充filegroupsrcs字段...

修改blah_library规则的实现

现在我有类似的东西:

_blah_provider = provider(fields=['transitive_deps'])

def _blah_library_impl(ctx):
    ...

    trans_deps = []
    for dep in ctx.attr.deps:
        trans_deps += dep[_blah_provider].trans_deps

    return _blah_provider(trans_deps=trans_deps)

blah_library = rule(impl=_blah_library_impl, ...)
Run Code Online (Sandbox Code Playgroud)

我尝试将以下内容添加到中_blah_library_impl,但由于native.filegroup在规则的实现(“ filegroup() cannot be called during the analysis phase”)中显然无法调用,所以它不起作用:

def _blah_library_impl(ctx):
    ...

    trans_deps = []
    for dep in ctx.attr.deps:
        trans_deps += dep[_blah_provider].trans_deps

    native.filegroup(
        name = ctx.attr.name + "__trans_deps",
        srcs = trans_deps,
    )

    return _blah_provider(trans_deps=trans_deps)
Run Code Online (Sandbox Code Playgroud)

Jos*_*art 1

我最终制定了自己的特殊filegroup规则,正如@Laszlo 的答案下的评论中所讨论的那样。这是原始代码,以防它对任何人来说都是有用的起点:

def _whl_deps_filegroup_impl(ctx):
    input_wheels = ctx.attr.src[_PyZProvider].transitive_wheels
    output_wheels = []
    for wheel in input_wheels:
        file_name = wheel.basename
        output_wheel = ctx.actions.declare_file(file_name)
        # TODO(josh): Use symlinks instead of copying. Couldn't figure out how
        # to do this due to issues with constructing absolute paths...
        ctx.actions.run(
            outputs=[output_wheel],
            inputs=[wheel],
            arguments=[wheel.path, output_wheel.path],
            executable="cp",
            mnemonic="CopyWheel")
        output_wheels.append(output_wheel)

    return [DefaultInfo(files=depset(output_wheels))]

whl_deps_filegroup = rule(
    _whl_deps_filegroup_impl,
    attrs = {
        "src": attr.label(),
    },
)
Run Code Online (Sandbox Code Playgroud)