Say I have something like the following.
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],
)
)
)
Is there a way to change the value of foo_aspect.attr._tool, either in WORKSPACE, or at the invocation of foo_rule? Former is much preferable.
The use case being that version and repository origin of _tool might change from project to project. When aspect resides in a repository shared by two projects, it does not make sense to create two branches for these two projects just for versioning of _tool.
After a lot of head scratching I found a rather complicated way of doing it.
Since the only thing that seems to be configuarable in
WORKSPACE.bazelduring loading phase is other workspaces / repositories, one could actually use target aliasing together with repository loading to mutiplex configuarable targets.Here is how it works.
First, define a new repository rule
new_virtual_repository, which creates repositories that does nothing but loading theBUILD.bazelandWORKSPACE.bazelfiles.Then, create an extension file
config.bzlwhich implements a function that generates theBUILD.bazelfile and load the virtual repository:Now in the aspect specification:
Finally, configure the actual tool in
WORKSPACE.bazel: