有没有办法以编程方式更改方面的私有属性?
Is there a way to change private attribute of an Aspect progammatically?
假设我有类似下面的内容。
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],
)
)
)
有没有办法在 WORKSPACE
中或调用 foo_rule
时更改 foo_aspect.attr._tool
的值?前者更可取。
_tool
的版本和存储库来源的用例可能因项目而异。当方面驻留在两个项目共享的存储库中时,为这两个项目创建两个分支只是为了 _tool
.
的版本控制没有意义
经过一番摸索,我发现了一种相当复杂的方法。
由于在加载阶段 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>")
假设我有类似下面的内容。
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],
)
)
)
有没有办法在 WORKSPACE
中或调用 foo_rule
时更改 foo_aspect.attr._tool
的值?前者更可取。
_tool
的版本和存储库来源的用例可能因项目而异。当方面驻留在两个项目共享的存储库中时,为这两个项目创建两个分支只是为了 _tool
.
经过一番摸索,我发现了一种相当复杂的方法。
由于在加载阶段 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>")