Есть ли способ изменить частный атрибут аспекта программно?

Скажем, у меня есть что-то вроде следующего.

def _foo_aspect_impl(target, ctx):
    # operations

    return FooInfo(...)

foo_aspect = aspect(implementation = _foo_aspect_impl,
    attr_aspects = ['deps'],
    attrs = dict(
        _tool = attr.Label(
            # defs
        ),
    )
)

def _foo_rule_impl(ctx):
    for dep in ctx.attr.deps:
        # do something with `dep[FooInfo]`

    return DefaultInfo(...)

foo_rule = rule(
    implementation = _foo_rule_impl,
    attrs = dict(
        "deps": attr.label_list(
            aspects = [foo_aspect],
        )
    )
)

Есть ли способ изменить значение foo_aspect.attr._tool, либо в WORKSPACE, или по призыву foo_rule? Бывшее намного предпочтительнее.

Вариант использования - это версия и происхождение репозитория _toolможет меняться от проекта к проекту. Когда аспект находится в репозитории, совместно используемом двумя проектами, нет смысла создавать две ветки для этих двух проектов только для управления версиями_tool.

1 ответ

Решение

После того, как я долго чесал голову, я нашел довольно сложный способ сделать это.

Поскольку единственное, что кажется настраиваемым в WORKSPACE.bazel во время фазы загрузки - это другие рабочие области / репозитории, можно фактически использовать псевдонимы целевых объектов вместе с загрузкой репозитория для мультиплексных конфигурируемых целей.

Вот как это работает.

Сначала определите новое правило репозитория new_virtual_repository, который создает репозитории, которые ничего не делают, кроме загрузки BUILD.bazel а также WORKSPACE.bazel файлы.

# repo.bzl

load("@bazel_tools//tools/build_defs/repo:utils.bzl", "workspace_and_buildfile")

def _new_virtual_repo_impl(ctx):
    # Create build file
    workspace_and_buildfile(ctx)
    return ctx.attr

new_virtual_repository = repository_rule(
    implementation = _new_virtual_repo_impl,
    attrs = dict(
        build_file = attr.label(allow_single_file = True),
        build_file_content = attr.string(),
        workspace_file = attr.label(allow_single_file = True),
        workspace_file_content = attr.string(),
    ),
    local = True,
)

Затем создайте файл расширения config.bzl который реализует функцию, которая генерирует BUILD.bazel файл и загрузите виртуальный репозиторий:

# config.bzl

load(":repo.bzl", "new_virtual_repository")
def config(tool):
    build_file_content = """
alias(
    name = "tool",
    actual = "%s",
""" % (tool)

    new_virtual_repository(
        name = "config_repo",
        build_file_content = build_file_content,
    )

Теперь в спецификации аспекта:

# aspect.bzl

foo_aspect = aspect(
    ...
    attrs = dict(
        _tool = attr.Label("@config_repo//:tool"),
    )
)

Наконец, настройте фактический инструмент в WORKSPACE.bazel:

# WORKSPACE.bazel

load("//:config.bzl", "config")
config(tool="<actual_tool_label>")
Другие вопросы по тегам