De-experimentalize starlark defined *rule class transitions* that *only read native options* and *don't have access to attributes that use select()*.
This necessitates de-experimentalizing the entire transition() function.
Still experimental:
- applying starlark-defined transitions on attributes
- applying starlark-defined transitions on starlark build settings anywhere
Still forbidden:
- reading configured attributes on rule class transitions
Newly forbidden:
- transitioning on native flags that are --experimental_ or --incomptaible_
RELNOTES: None.
PiperOrigin-RevId: 234602410
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
index 5117376..b6768ac 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/StarlarkDefinedConfigTransition.java
@@ -160,12 +160,13 @@
}
}
- private static class RegularTransition extends StarlarkDefinedConfigTransition {
+ /** A transition with a user-defined implementation function. */
+ public static class RegularTransition extends StarlarkDefinedConfigTransition {
private final BaseFunction impl;
private final StarlarkSemantics semantics;
private final StarlarkContext starlarkContext;
- public RegularTransition(
+ RegularTransition(
BaseFunction impl,
List<String> inputs,
List<String> outputs,
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
index b50310c..919ea2a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkAttr.java
@@ -278,6 +278,13 @@
if (starlarkDefinedTransition.isForAnalysisTesting()) {
builder.hasAnalysisTestTransition();
} else {
+ if (!env.getSemantics().experimentalStarlarkConfigTransitions()) {
+ throw new EvalException(
+ ast.getLocation(),
+ "Starlark-defined transitions on rule attributes is experimental and disabled by "
+ + "default. This API is in development and subject to change at any time. Use "
+ + "--experimental_starlark_config_transitions to use this experimental API.");
+ }
builder.hasStarlarkDefinedTransition();
}
builder.cfg(new StarlarkAttributeTransitionProvider(starlarkDefinedTransition));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
index d0a7ab0..6355db8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/config/ConfigGlobalLibrary.java
@@ -49,15 +49,10 @@
StarlarkContext context)
throws EvalException {
StarlarkSemantics semantics = env.getSemantics();
- if (!semantics.experimentalStarlarkConfigTransitions()) {
- throw new EvalException(
- location,
- "transition() is experimental and disabled by default. "
- + "This API is in development and subject to change at any time. Use "
- + "--experimental_starlark_config_transitions to use this experimental API.");
- }
- validateBuildSettingKeys(inputs, "input", location);
- validateBuildSettingKeys(outputs, "output", location);
+ validateBuildSettingKeys(
+ inputs, "input", location, semantics.experimentalStarlarkConfigTransitions());
+ validateBuildSettingKeys(
+ outputs, "output", location, semantics.experimentalStarlarkConfigTransitions());
return StarlarkDefinedConfigTransition.newRegularTransition(
implementation, inputs, outputs, semantics, context);
}
@@ -68,18 +63,29 @@
throws EvalException {
Map<String, Object> changedSettingsMap =
changedSettings.getContents(String.class, Object.class, "changed_settings dict");
- validateBuildSettingKeys(changedSettingsMap.keySet(), "output", location);
+ validateBuildSettingKeys(changedSettingsMap.keySet(), "output", location, true);
return StarlarkDefinedConfigTransition.newAnalysisTestTransition(changedSettingsMap, location);
}
private void validateBuildSettingKeys(
- Iterable<String> optionKeys, String keyErrorDescriptor, Location location)
+ Iterable<String> optionKeys,
+ String keyErrorDescriptor,
+ Location location,
+ boolean starlarkTransitionsEnabled)
throws EvalException {
HashSet<String> processedOptions = Sets.newHashSet();
for (String optionKey : optionKeys) {
if (!optionKey.startsWith(COMMAND_LINE_OPTION_PREFIX)) {
+ if (!starlarkTransitionsEnabled) {
+ throw new EvalException(
+ location,
+ "transitions on Starlark-defined build settings is experimental and "
+ + "disabled by default. This API is in development and subject to change at any"
+ + "time. Use --experimental_starlark_config_transitions to use this experimental "
+ + "API.");
+ }
try {
Label.parseAbsoluteUnchecked(optionKey);
} catch (IllegalArgumentException e) {
@@ -91,6 +97,16 @@
keyErrorDescriptor, optionKey),
e);
}
+ } else {
+ String optionName = optionKey.substring(COMMAND_LINE_OPTION_PREFIX.length());
+ if (optionName.startsWith("experimental_") || optionName.startsWith("incompatible_")) {
+ throw new EvalException(
+ location,
+ String.format(
+ "Invalid transition %s '%s'. Cannot transition on --experimental_* or "
+ + "--incompatible_* options",
+ keyErrorDescriptor, optionKey));
+ }
}
if (!processedOptions.add(optionKey)) {
throw new EvalException(location,
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
index aac3675..c2b82d1 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleFunctionsApi.java
@@ -337,8 +337,6 @@
defaultValue = "None",
named = true,
positional = false,
- enableOnlyWithFlag = FlagIdentifier.EXPERIMENTAL_STARLARK_CONFIG_TRANSITION,
- valueWhenDisabled = "None",
doc =
"If set, points to the configuration transition the rule will "
+ "apply to its own configuration before analysis.")
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkAttrTransitionProviderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkAttrTransitionProviderTest.java
index 5707c85..77b82a1 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkAttrTransitionProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkAttrTransitionProviderTest.java
@@ -348,7 +348,7 @@
"my_transition = transition(implementation = transition_func,",
" inputs = [],",
" outputs = ['//command_line_option:cpu',",
- " '//command_line_option:experimental_strict_java_deps'])",
+ " '//command_line_option:host_cpu'])",
"def impl(ctx): ",
" return []",
"my_rule = rule(",
@@ -369,7 +369,7 @@
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//test/skylark:test");
assertContainsEvent(
- "transition outputs [//command_line_option:experimental_strict_java_deps] were not "
+ "transition outputs [//command_line_option:host_cpu] were not "
+ "defined by transition function");
}
@@ -382,12 +382,12 @@
"test/skylark/my_rule.bzl",
"def transition_func(settings, attr):",
" if (len(settings) != 2",
- " or (not settings['//command_line_option:experimental_strict_java_deps'])",
+ " or (not settings['//command_line_option:host_cpu'])",
" or (not settings['//command_line_option:cpu'])):",
" fail()",
" return {'//command_line_option:cpu': 'k8'}",
"my_transition = transition(implementation = transition_func,",
- " inputs = ['//command_line_option:experimental_strict_java_deps',",
+ " inputs = ['//command_line_option:host_cpu',",
" '//command_line_option:cpu'],",
" outputs = ['//command_line_option:cpu'])",
"def impl(ctx): ",
@@ -747,6 +747,17 @@
}
@Test
+ public void testCannotTransitionWithoutFlag() throws Exception {
+ writeBasicTestFiles();
+ setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=false");
+
+ reporter.removeHandler(failFastHandler);
+ getConfiguredTarget("//test/skylark:test");
+ assertContainsEvent(
+ "Starlark-defined transitions on rule attributes is experimental and disabled by default");
+ }
+
+ @Test
public void testOptionConversionDynamicMode() throws Exception {
// TODO(waltl): check that dynamic_mode is parsed properly.
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
index dec9ebf..ba35ef9 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/StarlarkRuleTransitionProviderTest.java
@@ -30,7 +30,6 @@
@Test
public void testOutputOnlyTransition() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -54,7 +53,6 @@
@Test
public void testInputAndOutputTransition() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -84,8 +82,7 @@
@Test
public void testBuildSettingCannotTransition() throws Exception {
- setSkylarkSemanticsOptions(
- "--experimental_starlark_config_transitions=true", "--experimental_build_setting_api=true");
+ setSkylarkSemanticsOptions("--experimental_build_setting_api=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -112,7 +109,6 @@
@Test
public void testBadCfgInput() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/rules.bzl",
"def _impl(ctx):",
@@ -131,7 +127,6 @@
@Test
public void testMultipleReturnConfigs() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -157,7 +152,6 @@
@Test
public void testCanDoBadStuffWithParameterizedTransitionsAndSelects() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -202,7 +196,6 @@
@Test
public void testLabelTypedAttrReturnsLabelNotDep() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=true");
scratch.file(
"test/transitions.bzl",
"def _impl(settings, attr):",
@@ -240,28 +233,23 @@
}
@Test
- public void testCannotTransitionWithoutFlag() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=false");
+ public void testCannotTransitionOnBuildSettingWithoutFlag() throws Exception {
+ setSkylarkSemanticsOptions(
+ "--experimental_starlark_config_transitions=false", "--experimental_build_setting_api");
scratch.file(
"test/transitions.bzl",
- "def _impl(settings, attr):",
- " return {'//command_line_option:test_arg': ['post-transition']}",
- "my_transition = transition(implementation = _impl, inputs = [],",
- " outputs = ['//command_line_option:test_arg'])");
- scratch.file(
- "test/rules.bzl",
- "load('//test:transitions.bzl', 'my_transition')",
- "def _impl(ctx):",
- " return []",
- "my_rule = rule(implementation = _impl, cfg = my_transition)");
- scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
+ "def _transition_impl(settings, attr):",
+ " return {'//test:cute-animal-fact': 'puffins mate for life'}",
+ "my_transition = transition(",
+ " implementation = _transition_impl,",
+ " inputs = [],",
+ " outputs = ['//test:cute-animal-fact']",
+ ")");
+ writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//test");
- assertContainsEvent(
- "transition() is experimental and disabled by default. This API is in "
- + "development and subject to change at any time. Use "
- + "--experimental_starlark_config_transitions to use this experimental API.");
+ assertContainsEvent("transitions on Starlark-defined build settings is experimental");
}
private void writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests() throws Exception {
@@ -414,4 +402,26 @@
getConfiguredTarget("//test");
assertContainsEvent("too many (2) positional arguments in call to _impl(settings)");
}
+
+ @Test
+ public void testCannotTransitionOnExperimentalFlag() throws Exception {
+ scratch.file(
+ "test/transitions.bzl",
+ "def _impl(settings, attr):",
+ " return {'//command_line_option:experimental_build_setting_api': True}",
+ "my_transition = transition(implementation = _impl, inputs = [],",
+ " outputs = ['//command_line_option:experimental_build_setting_api'])");
+ scratch.file(
+ "test/rules.bzl",
+ "load('//test:transitions.bzl', 'my_transition')",
+ "def _impl(ctx):",
+ " return []",
+ "my_rule = rule(implementation = _impl, cfg = my_transition)");
+ scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
+
+ reporter.removeHandler(failFastHandler);
+ getConfiguredTarget("//test");
+ assertContainsEvent("Cannot transition on --experimental_* or --incompatible_* options");
+ }
}
+
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
index 90c7efa..576f055 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
@@ -1154,31 +1154,6 @@
}
@Test
- public void testTransitionGuardedByExperimentalFlag() throws Exception {
- setSkylarkSemanticsOptions("--experimental_starlark_config_transitions=false");
-
- scratch.file(
- "test/extension.bzl",
- "def custom_rule_impl(ctx):",
- " return []",
- "def transition_func(settings):",
- " return settings",
- "my_transition = transition(implementation = transition_func, inputs = [], outputs = [])",
- "",
- "custom_rule = rule(implementation = custom_rule_impl)");
-
- scratch.file(
- "test/BUILD",
- "load('//test:extension.bzl', 'custom_rule')",
- "",
- "custom_rule(name = 'r')");
-
- reporter.removeHandler(failFastHandler);
- getConfiguredTarget("//test:r");
- assertContainsEvent("transition() is experimental and disabled by default");
- }
-
- @Test
public void testNoOutputListAttrDefault() throws Exception {
setSkylarkSemanticsOptions("--incompatible_no_output_attr_default=true");
@@ -2152,7 +2127,7 @@
@Test
public void testAnalysisTestTransitionOnAnalysisTest() throws Exception {
- useConfiguration("--experimental_strict_java_deps=OFF");
+ useConfiguration("--copt=yeehaw");
scratch.file(
"test/extension.bzl",
@@ -2160,21 +2135,21 @@
"MyDep = provider()",
"",
"def outer_rule_impl(ctx):",
- " return [MyInfo(strict_java_deps = ctx.fragments.java.strict_java_deps),",
+ " return [MyInfo(copts = ctx.fragments.cpp.copts),",
" MyDep(info = ctx.attr.dep[0][MyInfo]),",
" AnalysisTestResultInfo(success = True, message = 'message contents')]",
"def inner_rule_impl(ctx):",
- " return [MyInfo(strict_java_deps = ctx.fragments.java.strict_java_deps)]",
+ " return [MyInfo(copts = ctx.fragments.cpp.copts)]",
"",
"my_transition = analysis_test_transition(",
" settings = {",
- " '//command_line_option:experimental_strict_java_deps' : 'WARN' }",
+ " '//command_line_option:copt' : ['cowabunga'] }",
")",
"inner_rule = rule(implementation = inner_rule_impl,",
- " fragments = ['java'])",
+ " fragments = ['cpp'])",
"outer_rule_test = rule(",
" implementation = outer_rule_impl,",
- " fragments = ['java'],",
+ " fragments = ['cpp'],",
" analysis_test = True,",
" attrs = {",
" 'dep': attr.label(cfg = my_transition),",
@@ -2197,8 +2172,8 @@
StructImpl outerDepInfo = (StructImpl) outerTarget.get(myDepKey);
StructImpl innerInfo = (StructImpl) outerDepInfo.getValue("info");
- assertThat(outerInfo.getValue("strict_java_deps")).isEqualTo("off");
- assertThat(innerInfo.getValue("strict_java_deps")).isEqualTo("warn");
+ assertThat((SkylarkList) outerInfo.getValue("copts")).containsExactly("yeehaw");
+ assertThat((SkylarkList) innerInfo.getValue("copts")).containsExactly("cowabunga");
}
@Test
@@ -2209,7 +2184,7 @@
" return []",
"my_transition = analysis_test_transition(",
" settings = {",
- " '//command_line_option:experimental_strict_java_deps' : 'WARN' }",
+ " '//command_line_option:test_arg' : ['yeehaw'] }",
")",
"",
"custom_rule = rule(",
@@ -2347,7 +2322,7 @@
"",
"my_transition = analysis_test_transition(",
" settings = {",
- " '//command_line_option:experimental_strict_java_deps' : 'WARN' }",
+ " '//command_line_option:test_arg' : ['yeehaw'] }",
")",
"",
"inner_rule_test = rule(",
@@ -2410,7 +2385,7 @@
"",
"my_transition = analysis_test_transition(",
" settings = {",
- " '//command_line_option:experimental_strict_java_deps' : 'WARN' }",
+ " '//command_line_option:test_arg' : ['yeehaw'] }",
")",
"dep_rule = rule(",
" implementation = dep_rule_impl,",
@@ -2506,7 +2481,7 @@
"",
"my_transition = analysis_test_transition(",
" settings = {",
- " '//command_line_option:experimental_strict_java_deps' : 'WARN' }",
+ " '//command_line_option:test_arg' : ['yeehaw'] }",
")",
"dep_rule = rule(",
" implementation = dep_rule_impl,",