Skip to content

Commit

Permalink
Add example of attaching transitions and transitioning on build setti…
Browse files Browse the repository at this point in the history
…ng (bazelbuild#165)

Work towards bazelbuild#154

This one actually covers quite a bit of stuff, but it made sense to me to keep it all together - let me know if you think it's too dense
  • Loading branch information
juliexxia authored May 15, 2020
1 parent b69c13b commit ab1fda2
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
15 changes: 15 additions & 0 deletions rules/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,18 @@ py_repositories()
load("@rules_python//python:pip.bzl", "pip_repositories")

pip_repositories()

# Load Skylib 0.9.0 as instructed at
# https://github.com/bazelbuild/bazel-skylib/releases/tag/1.0.2

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "bazel_skylib",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
],
sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
bazel_skylib_workspace()
16 changes: 16 additions & 0 deletions rules/starlark_configurations/attaching_transitions_to_rules/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# We don't actually need an external repo to define Starlark settings. But
# Skylib provides convenience macros that reduce boilerplate, so we'll use that
# here.
#
# See https://docs.bazel.build/versions/master/skylark/config.html and
# https://github.com/bazelbuild/bazel-skylib) for more info.
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load(":defs.bzl", "shirt", "piece")

# Define a build setting using the skylib pre-defined settings
string_flag(name = "color", build_setting_default = "black")

# Define a rule with two dependencies
shirt(name = "tee", sleeve = ":sleeve", back = ":back")
piece(name = "sleeve")
piece(name = "back")
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
This is an example of how to define and use a transition on a build setting. Rules can attach transitions
in two places: (1) directly on the rule and (2) onto an attribute. It covers the following topics
- attaching a transition to a rule
- attaching a transition to an attribute
- reading the build setting value of a target
- reading the build setting value of a transitioned dependency
- reading the build setting value of a non-transitioned dependency

To test it out, cd to this directory and run the following:
```
$ bazel build :tee
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Load the provider of the pre-made settings defined in bazel_skylib.
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")

# Define two different transitions that both transition the `color` build setting
# we defined in the BUILD.
def _blue_impl(settings, attr):
_ignore = settings, attr

return {"//starlark_configurations/attaching_transitions_to_rules:color": "blue"}

blue_transition = transition(
implementation = _blue_impl,
inputs = [],
outputs = ["//starlark_configurations/attaching_transitions_to_rules:color"],
)

def _red_impl(settings, attr):
_ignore = settings, attr

return {"//starlark_configurations/attaching_transitions_to_rules:color": "red"}

red_transition = transition(
implementation = _red_impl,
inputs = [],
outputs = ["//starlark_configurations/attaching_transitions_to_rules:color"],
)

def _impl(ctx):
# Access the value of //starlark_configurations/attaching_transitions_to_rules:color for the target (blue).
print("shirt color: " + ctx.attr._color[BuildSettingInfo].value)
# Access the value of //starlark_configurations/attaching_transitions_to_rules:color for the transitioned dep (red).
# Note that you have to index by [0] here for the transitioned dep and you don't need to
# do so below - this is because attribute-attached transitions can transition to multiple
# new configurations so you must specify which one you want.
print("sleeve color: " + ctx.attr.sleeve[0][BuildSettingInfo].value)
# Access the value of //starlark_configurations/attaching_transitions_to_rules:color for the non-transitioned dep (blue).
print("back color: " + ctx.attr.back[BuildSettingInfo].value)
return []

shirt = rule(
implementation = _impl,
# Attaching at rule transitions the configuration of this target and all its dependencies
# (until it gets overwritten again, for example...)
cfg = blue_transition,
attrs = {
# Attaching to an attribute transitions the configuration of this dependency (and
# all its dependencies)
"sleeve": attr.label(cfg = red_transition),
# Here is an attribute with no transition so it will inherit its parent's --//:color
"back": attr.label(),
# Depend on the build setting so that we can access it in the rule implementation.
# Use a private attribute (one that is prefixed with "_") so that target writers
# can't override the value.
"_color": attr.label(default = ":color"),
# This attribute is required to use starlark transitions. It allows
# whitelisting usage of this rule. For more information, see
# https://docs.bazel.build/versions/master/skylark/config.html#user-defined-transitions
"_whitelist_function_transition": attr.label(
default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
),
},
)

def _piece_impl(ctx):
return ctx.attr._color[BuildSettingInfo]

piece = rule(
implementation = _piece_impl,
attrs = {
# Depend on the build setting so that we can access it in the rule implementation.
# Use a private attribute (one that is prefixed with "_") so that target writers
# can't override the value.
"_color": attr.label(default = ":color")
}
)

0 comments on commit ab1fda2

Please sign in to comment.