Better error messaging for needing transition whitelist + updated docs. Allow the way throw in a note about attaching to starlark transitions to native rules since we've been getting a lot of questions about that recently.
#7056
PiperOrigin-RevId: 296113789
diff --git a/site/docs/skylark/config.md b/site/docs/skylark/config.md
index 1d1343a..cadf03d 100644
--- a/site/docs/skylark/config.md
+++ b/site/docs/skylark/config.md
@@ -331,6 +331,23 @@
is how we change configuration of
configured targets in the build graph.
+> IMPORTANT: In order to use Starlark transitions, you need to attach a
+> special attribute to the rule to which the transition is attached:
+>
+> ```python
+> "_whitelist_function_transition": attr.label(
+> default = "@bazel_tools//tools/whitelists/function_transition_whitelist"
+> )
+> ```
+>
+> By adding transitions you can pretty easily explode the size of
+> your build graph. This sets a whitelist on the packages in which you can
+> create targets of this rule. The default value in the codeblock above
+> whitelists everything. But if you'd like to restrict who is using your rule,
+> you can set that attribute to point to your own custom whitelist.
+> Contact bazel-discuss@googlegroups.com if you'd like advice or assistance
+> understanding how transitions can affect on your build performance.
+
### Defining Transitions in Starlark
Transitions define configuration changes between rules. For example, a request
@@ -418,6 +435,11 @@
edge transition) and transition their dependencies' configurations (outgoing
edge transition).
+NOTE: There is currently no way to attach Starlark transitions to native rules.
+If you need to do this, contact
+bazel-discuss@googlegroups.com
+and we can help you try to figure out a workaround.
+
#### Incoming Edge Transitions
Incoming edge transitions are activated by attaching a `transition` object
(created by `transition()`) to `rule()`'s `cfg` parameter:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 9fdae97..7100116 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -99,9 +99,7 @@
import java.util.Map;
import java.util.concurrent.ExecutionException;
-/**
- * A helper class to provide an easier API for Skylark rule definitions.
- */
+/** A helper class to provide an easier API for Skylark rule definitions. */
public class SkylarkRuleClassFunctions implements SkylarkRuleFunctionsApi<Artifact> {
// TODO(bazel-team): Copied from ConfiguredRuleClassProvider for the transition from built-in
@@ -266,10 +264,12 @@
"Expected list of strings or dictionary of string -> string for 'fields'");
fieldNames = list;
} else if (fields instanceof Dict) {
- Map<String, String> dict = SkylarkType.castMap(
- fields,
- String.class, String.class,
- "Expected list of strings or dictionary of string -> string for 'fields'");
+ Map<String, String> dict =
+ SkylarkType.castMap(
+ fields,
+ String.class,
+ String.class,
+ "Expected list of strings or dictionary of string -> string for 'fields'");
fieldNames = dict.keySet();
}
return SkylarkProvider.createUnexportedSchemaful(fieldNames, thread.getCallerLocation());
@@ -362,8 +362,7 @@
builder.addRequiredToolchains(
collectToolchainLabels(
- toolchains.getContents(String.class, "toolchains"),
- bazelContext.getRepoMapping()));
+ toolchains.getContents(String.class, "toolchains"), bazelContext.getRepoMapping()));
if (!buildSetting.equals(Starlark.NONE) && !cfg.equals(Starlark.NONE)) {
throw Starlark.errorf(
@@ -439,8 +438,7 @@
}
private static ImmutableList<Label> collectToolchainLabels(
- Iterable<String> rawLabels,
- ImmutableMap<RepositoryName, RepositoryName> mapping)
+ Iterable<String> rawLabels, ImmutableMap<RepositoryName, RepositoryName> mapping)
throws EvalException {
ImmutableList.Builder<Label> requiredToolchains = new ImmutableList.Builder<>();
for (String rawLabel : rawLabels) {
@@ -457,8 +455,7 @@
}
private static ImmutableList<Label> collectConstraintLabels(
- Iterable<String> rawLabels,
- ImmutableMap<RepositoryName, RepositoryName> mapping)
+ Iterable<String> rawLabels, ImmutableMap<RepositoryName, RepositoryName> mapping)
throws EvalException {
ImmutableList.Builder<Label> constraintLabels = new ImmutableList.Builder<>();
for (String rawLabel : rawLabels) {
@@ -673,15 +670,16 @@
return Starlark.NONE;
}
- /**
- * Export a RuleFunction from a Skylark file with a given name.
- */
+ /** Export a RuleFunction from a Skylark file with a given name. */
public void export(Label skylarkLabel, String ruleClassName) throws EvalException {
Preconditions.checkState(ruleClass == null && builder != null);
this.skylarkLabel = skylarkLabel;
if (type == RuleClassType.TEST != TargetUtils.isTestRuleName(ruleClassName)) {
- throw new EvalException(definitionLocation, "Invalid rule class name '" + ruleClassName
- + "', test rule class names must end with '_test' and other rule classes must not");
+ throw new EvalException(
+ definitionLocation,
+ "Invalid rule class name '"
+ + ruleClassName
+ + "', test rule class names must end with '_test' and other rule classes must not");
}
// Thus far, we only know if we have a rule transition. While iterating through attributes,
// check if we have an attribute transition.
@@ -742,7 +740,9 @@
throw new EvalException(
getLocation(),
String.format(
- "Use of Starlark transition without whitelist: %s %s",
+ "Use of Starlark transition without whitelist attribute"
+ + " '_whitelist_function_transition'. See Starlark transitions documentation"
+ + " for details and usage: %s %s",
builder.getRuleDefinitionEnvironmentLabel(), builder.getType()));
}
} else {