aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Michael Staib <mstaib@google.com>2017-03-06 18:59:58 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-03-07 10:47:10 +0000
commit3386651f0bfe9d9dd22d7ef00e15e917792a4765 (patch)
tree1a0b2d1fea4c9815c0cb2f19adde8ab2b50c965a
parente8d1177eef9a9798d2b971630b8cea59471eec33 (diff)
Add the label_keyed_string_dict design doc to Bazel's site.
-- PiperOrigin-RevId: 149319159 MOS_MIGRATED_REVID=149319159
-rw-r--r--site/designs/_posts/2017-03-03-label-keyed-string-dict-type.md139
1 files changed, 139 insertions, 0 deletions
diff --git a/site/designs/_posts/2017-03-03-label-keyed-string-dict-type.md b/site/designs/_posts/2017-03-03-label-keyed-string-dict-type.md
new file mode 100644
index 0000000000..76f6b00a67
--- /dev/null
+++ b/site/designs/_posts/2017-03-03-label-keyed-string-dict-type.md
@@ -0,0 +1,139 @@
+---
+layout: contribute
+title: Label-keyed String Dictionary Type for Build Attributes
+---
+
+# Label-keyed String Dictionary Type for Build Attributes
+
+**Status**: Implemented in
+[5e9e194](https://github.com/bazelbuild/bazel/commit/5e9e1949f4c08ce09665b92aadf7ec7e518aab6a)
+
+**Author**: [Michael Staib](mstaib@google.com)
+
+## Background/Motivation
+
+For future work in the realm of allowing Bazel users to define configuration
+flags, the `config_setting` rule will need to be able to test configuration
+values defined by labels rather than strings. The current solution uses a
+dictionary from string (the flag to check the value of) to string (the value
+to check against). It makes sense, then, to use a dictionary from label (the
+flag to check the value of) to string (the value to check against) for
+user-defined configuration which is defined by a label.
+
+Additionally, for work which relates to setting such user-defined configuration,
+rules should be able to declare similar dictionaries for the purposes of setting
+those same flags.
+
+An example incorporating both testing and setting such flags:
+
+```
+flag_rule(
+ name = "beep",
+ values = ["boop", "bop", "bump"],
+ default = "bump"
+)
+
+config_setting(
+ name = "beep#boop",
+ flag_values = {
+ ":beep": "boop"
+ }
+)
+
+transition_rule(
+ name = "configuration",
+ deps = [
+ ":lib"
+ ],
+ sets_flags = {
+ ":beep": "boop"
+ }
+)
+
+library_rule(
+ name = "lib"
+ deps = select({
+ ":beep#boop": [":boop_dep"],
+ "//conditions:default": [":other_dep"]
+ })
+)
+```
+
+## New attribute type: LABEL_KEYED_STRING_DICT
+In order to handle these flag values, the BUILD language will need the ability
+to express a mapping from a label (a flag's label, to be precise) to a string
+(the flag's value). This will be added as `BuildType.LABEL_KEYED_STRING_DICT` in
+native rules, and as `attr.label_keyed_string_dict()` in Skylark (taking the
+same parameters as `attr.label_list()`). This will have to be serializable
+to query `--output=proto` format.
+
+### Native rule representation
+Native rules will be able to take the attribute's value using an
+`AttributeMapper`, as normal. In this case, the type returned will be
+`Map<Label, String>`. In conjunction with `RuleContext.getPrerequisites`, this
+can be used to get both the target and the string value associated with it by
+iterating over the return value from `getPrerequisites` and looking up the
+labels of the `TransitiveInfoCollection`s in the map.
+
+### Skylark representation
+Skylark rules must render some representation of this structure in
+`ctx.attr.<attrname>`. The only restriction on Skylark dictionary keys is that
+they must be immutable, which the various `ConfiguredTarget`s are (although they
+must be annotated as such). Accordingly, the value of `ctx.attr.<attrname>` is a
+dictionary mapping Target to string. This will have to be changed to be another
+special case in the `SkylarkRuleContext`.
+
+Because each target in an attribute will undergo the same transition - if any -
+and the transition of the target itself will always be the same, the keys of
+this dict will be unique - i.e., there will be no collisions - as long as the
+labels used to construct it were unique.
+
+### Handling collisions when converting attribute values from Skylark
+Labels are special in that there are multiple ways (and possibly multiple
+encodings!) to represent them in a BUILD or Skylark file which are not the same
+from Skylark's point of view. In the package `//label`, the strings `"label"`,
+`":label"`, `"//label"`, and `"//label:label"` all evaluate to the same `Label`
+when they are picked up by Bazel, but they will be different keys in the dict
+created by Skylark, where they are merely strings. Skylark does have a label
+type (constructed with `Label("//label")`, yet another way of representing the
+same label), and Bazel does accept it for `LABEL` attributes, but most uses of
+label-type attributes take advantage of Bazel's automatic conversion of strings
+in label-type attributes. That conversion does not happen until the Skylark
+value enters the build system at a rule attribute, at which point the value may
+have been mutated, read, and passed around in Skylark several times.
+
+In Skylark, it is an error for a dictionary literal to contain multiple items
+with the same key. For consistency and simplicity, `LABEL_KEYED_STRING_DICT`
+will throw a `ConversionException` in its convert method if two of the Skylark
+dict's keys evaluate to the same label, even if they also have the same value.
+This only covers the case where the two keys are distinct strings; if two
+identical keys are used in a dictionary literal, there will be an error in
+Skylark before this logic ever sees it. Mutations of a key (i.e.,
+`dictionary[key] = value` for a `key` which is already in the dictionary) will
+continue to be allowed as normal.
+
+## Testing Plan
+
+* Conversion exception for non-dict values
+* Conversion exception for dicts other than string-to-string
+* Conversion exception for dicts with multiple keys evaluating to the same label
+* Conversion exception for dicts with invalid labels as keys
+* Successfully converts to `Map<Label, String>`
+* Successfully converts to query proto
+* Successfully converts to query XML
+* Successfully outputs in build format from query
+* visitLabels visits the labels in the keys
+* Skylark can define `label_keyed_string_dict` attributes and receive them as a
+ dict of Target to string
+* Skylark can define `label_keyed_string_dict` attributes with provider
+ requirements and have them be respected
+* Skylark can define `label_keyed_string_dict` attributes with filetype
+ requirements and have them be respected
+* Skylark can define `label_keyed_string_dict` attributes and require they not
+ be empty
+* Skylark can define `label_keyed_string_dict` attributes and make them
+ mandatory
+* Skylark can define `label_keyed_string_dict` attributes and set the default
+ value
+* Skylark can define `label_keyed_string_dict` attributes and have Aspects
+ follow them