Rules in Bazel often need information from their dependencies. My previous post touched on a special case of this: figuring out what a dependency’s runfiles are. However, Skylark is actually capable of passing arbitrary information between rules using a system known as providers.
Suppose we have a rule, analyze_flavors
, that figures out what all of the flavors are in a dish. Our build file looks like:
load(":food.bzl", "analyze_flavors") analyze_flavors( name = "burger", ingredients = [ ":beef", ":ketchup", ], ) analyze_flavors( name = "beef", tastes_like = "umame", ) analyze_flavors( name = "ketchup", tastes_like = "sweet", )
We want to build up a flavor profile for :burger
, based on its ingredients.
To do this, food.bzl
looks like:
def _flavor_impl(ctx): # Build up a flavor profile from this rule & its ingredients. flavor_profile = [] for ingredient in ctx.attr.ingredients: if ingredient.flavor != None: flavor_profile += ingredient.flavor if ctx.attr.tastes_like != "": flavor_profile += [ctx.attr.tastes_like] # Write the list of flavors to a file. ctx.file_action( output = ctx.outputs.out, content = "%s tastes like %sn" % ( ctx.label.name, " and ".join(flavor_profile)) ) # Return the list of flavors so it can be used by rules that depend on this. return struct(flavor = flavor_profile) analyze_flavors = rule( attrs = { "ingredients": attr.label_list(), "tastes_like": attr.string(), }, outputs = {"out": "flavors-of-%{name}"}, implementation = _flavor_impl, )
The highlighted lines are where the rule returns a provider, flavor
, to be consumed by its reverse dependencies (the targets depending on it).
Our BUILD file gives us the following build graph:
:burger
depends on :beef
and :ketchup
. :beef
and :ketchup
each provide :burger
with a flavor. Thus, if we build :burger
and check its output file, we get:
$ bazel build :burger INFO: Found 1 target... Target //:burger up-to-date: bazel-bin/flavors-of-burger INFO: Elapsed time: 0.270s, Critical Path: 0.00s INFO: Build completed successfully, 2 total actions $ cat bazel-bin/flavors-of-burger burger tastes like umame and sweet
This can be used to communicate rich information from rule-to-rule in Skylark. See the Skylark cookbook for another example of providers.