Есть ли способ изменить частный атрибут аспекта программно?
Скажем, у меня есть что-то вроде следующего.
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>")