In Bazel, is there a way to access all the providers of a Target without prior knowledge of what provider type a target could contain ?
I'd like a rule implementation to simply returns the "result" (providers) of another rule:
def _myrule_impl(ctx):
for p in ctx.attr.parent_rule:
# Error: type 'Target' is not iterable
p = ctx.attr.target_rule.providers
# Error: <target //:main> (rule 'other_rule') doesn't have provider 'providers'
return ctx.attr.parent_rule
myrule = rule(
implementation = _myrule_impl,
attrs = {
"parent_rule": attr.label(),
}
)
I could reconstruct the list of providers by accessing them via their types (e.g. ctx.attr.parent_rule[DefaultInfo]
but it's error prone and would break easily if not maintained properly (e.g. another rule upstream adds a new provider to a target not checked in myrule
therefore breaking downstream).
It seems there must be an easy way to do that but the documentation is not clear on exactly how the providers are stored (looks like something ad-hoc, and not a dict or list).
I'm also interested in any other alternative method for a "pass-through" rule in case there is an easier way to do it.
Providers are more or less considered private implementation details of rules, so there isn't a way to enumerate the providers of a target. See this comment in the code, for example:
(that is, while print(target)
will print provider names, doing str(target)
in Starlark won't contain the same info, and things like getattr
/ hasattr
don't work for providers)
This does make things like "wrapper rules" or "pass through rules" more difficult, but there are other mechanisms being implemented for this such as https://github.com/bazelbuild/bazel/issues/19507