Report fragments Starlark transitions use.
Also add some straggler native transitions.
With all transitions converted, also remove legacy
PatchTransition.patch(BuildOptions) and
SplitTransition.split(BuildOptions).
In service of https://github.com/bazelbuild/bazel/issues/11258.
PiperOrigin-RevId: 317383960
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ConfigurationTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ConfigurationTransition.java
index 6232b13..4b62ec5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ConfigurationTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ConfigurationTransition.java
@@ -42,6 +42,19 @@
}
/**
+ * {@link #requiresOptionFragments()} variation for Starlark transitions, which need a {@link
+ * BuildOptions} instance to map required options to their {@link FragmentOptions}.
+ *
+ * <p>Non-Starlark transitions should override {@link #requiresOptionFragments()} and ignore this.
+ *
+ * <p>Callers may also ignore this if they know they're not calling into a Starlark transition.
+ */
+ default ImmutableSet<Class<? extends FragmentOptions>> requiresOptionFragments(
+ BuildOptions options) {
+ return requiresOptionFragments();
+ }
+
+ /**
* Returns the map of {@code BuildOptions} after applying this transition. The returned map keys
* are only used for dealing with split transitions. Patch transitions, including internal, native
* Patch transitions, should return a single entry map with key {@code PATCH_TRANSITION_KEY}.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/PatchTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/PatchTransition.java
index 99bff12..79341ba 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/PatchTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/PatchTransition.java
@@ -58,22 +58,6 @@
/**
* Applies the transition.
*
- * <p>This method is being deprecated (https://github.com/bazelbuild/bazel/issues/11258). Please
- * use {@link #patch(BuildOptionsView, EventHandler)} for new uses.
- *
- * @param options the options representing the input configuration to this transition. <b>DO NOT
- * MODIFY THIS VARIABLE WITHOUT CLONING IT FIRST!</b>
- * @param eventHandler
- * @return the options representing the desired post-transition configuration
- */
- default BuildOptions patch(BuildOptions options, EventHandler eventHandler) {
- throw new UnsupportedOperationException(
- "Either this or patch(BuildOptionsView) must be overridden");
- }
-
- /**
- * Applies the transition.
- *
* <p>Blaze throws an {@link IllegalArgumentException} if this method reads any options fragment
* not declared in {@link ConfigurationTransition#requiresOptionFragments}.
*
@@ -82,11 +66,7 @@
* @param eventHandler
* @return the options representing the desired post-transition configuration
*/
- default BuildOptions patch(BuildOptionsView options, EventHandler eventHandler) {
- // Escape hatch for implementers of the BuildOptions method: provide uninhibited access. When
- // all implementers use this variation we'll remove this default implementation.
- return patch(options.underlying(), eventHandler);
- }
+ BuildOptions patch(BuildOptionsView options, EventHandler eventHandler);
@Override
default Map<String, BuildOptions> apply(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/SplitTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/SplitTransition.java
index d3b7d0b..c39e7c1 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/SplitTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/SplitTransition.java
@@ -42,32 +42,12 @@
* is a noop. The key values are used as dict keys in ctx.split_attr, so human-readable strings
* are recommended.
*
- * <p>This method is being deprecated (https://github.com/bazelbuild/bazel/issues/11258). Please
- * use {@link #split(BuildOptionsView, EventHandler)} for new uses.
- *
- * <p>Returning an empty or null list triggers a {@link RuntimeException}.
- */
- default Map<String, BuildOptions> split(BuildOptions buildOptions, EventHandler eventHandler) {
- throw new UnsupportedOperationException(
- "Either this or patch(BuildOptionsView) must be overridden");
- }
-
- /**
- * Returns the map of {@code BuildOptions} after splitting, or the original options if this split
- * is a noop. The key values are used as dict keys in ctx.split_attr, so human-readable strings
- * are recommended.
- *
* <p>Blaze throws an {@link IllegalArgumentException} if this method reads any options fragment
* not declared in {@link ConfigurationTransition#requiresOptionFragments}.
*
* <p>Returning an empty or null list triggers a {@link RuntimeException}.
*/
- default Map<String, BuildOptions> split(
- BuildOptionsView buildOptions, EventHandler eventHandler) {
- // Escape hatch for implementers of the BuildOptions method: provide uninhibited access. When
- // all implementers use this variation we'll remove this default implementation.
- return split(buildOptions.underlying(), eventHandler);
- }
+ Map<String, BuildOptions> split(BuildOptionsView buildOptions, EventHandler eventHandler);
/**
* Returns true iff {@code option} and {@code splitOptions} are equal.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/TransitionUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/TransitionUtil.java
index 60a20ea..059e53c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/TransitionUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/TransitionUtil.java
@@ -26,6 +26,6 @@
*/
public static BuildOptionsView restrict(
ConfigurationTransition transition, BuildOptions options) {
- return new BuildOptionsView(options, transition.requiresOptionFragments());
+ return new BuildOptionsView(options, transition.requiresOptionFragments(options));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
index f089496..b99c527 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java
@@ -135,7 +135,7 @@
}
/** For all the options in the BuildOptions, build a map from option name to its information. */
- private static Map<String, OptionInfo> buildOptionInfo(BuildOptions buildOptions) {
+ static ImmutableMap<String, OptionInfo> buildOptionInfo(BuildOptions buildOptions) {
ImmutableMap.Builder<String, OptionInfo> builder = new ImmutableMap.Builder<>();
ImmutableSet<Class<? extends FragmentOptions>> optionClasses =
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttributeTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttributeTransitionProvider.java
index 78a6fd2..ebb6cc6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttributeTransitionProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkAttributeTransitionProvider.java
@@ -21,6 +21,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
@@ -104,7 +105,11 @@
*/
@Override
public final Map<String, BuildOptions> split(
- BuildOptions buildOptions, EventHandler eventHandler) {
+ BuildOptionsView buildOptionsView, EventHandler eventHandler) {
+ // Starlark transitions already have logic to enforce they only access declared inputs and
+ // outputs. Rather than complicate BuildOptionsView with more access points to BuildOptions,
+ // we just use the original BuildOptions and trust the transition's enforcement logic.
+ BuildOptions buildOptions = buildOptionsView.underlying();
try {
return applyAndValidate(
buildOptions, starlarkDefinedConfigTransition, attrObject, eventHandler);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleTransitionProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleTransitionProvider.java
index 34d2a26..6e0ae68 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleTransitionProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkRuleTransitionProvider.java
@@ -19,6 +19,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
@@ -106,8 +107,12 @@
// TODO(b/121134880): validate that the targets these transitions are applied on don't read any
// attributes that are then configured by the outputs of these transitions.
@Override
- public BuildOptions patch(BuildOptions buildOptions, EventHandler eventHandler) {
+ public BuildOptions patch(BuildOptionsView buildOptionsView, EventHandler eventHandler) {
Map<String, BuildOptions> result;
+ // Starlark transitions already have logic to enforce they only access declared inputs and
+ // outputs. Rather than complicate BuildOptionsView with more access points to BuildOptions,
+ // we just use the original BuildOptions and trust the transition's enforcement logic.
+ BuildOptions buildOptions = buildOptionsView.underlying();
try {
result =
applyAndValidate(
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkTransition.java
index 2456136..9a8d47c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkTransition.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkTransition.java
@@ -19,11 +19,14 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.StarlarkDefinedConfigTransition;
import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
+import com.google.devtools.build.lib.analysis.starlark.FunctionTransitionUtil.OptionInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.BuildType.SelectorList;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
@@ -77,6 +80,28 @@
return starlarkDefinedConfigTransition.getOutputs();
}
+ @Override
+ public ImmutableSet<Class<? extends FragmentOptions>> requiresOptionFragments(
+ BuildOptions buildOptions) {
+ // TODO(bazel-team): complexity cleanup: merge buildOptionInfo with TransitiveOptionDetails.
+ Map<String, OptionInfo> optionToFragment = FunctionTransitionUtil.buildOptionInfo(buildOptions);
+ ImmutableSet.Builder<Class<? extends FragmentOptions>> fragments = ImmutableSet.builder();
+ for (String optionStarlarkName : Iterables.concat(getInputs(), getOutputs())) {
+ // TODO(bazel-team): support Starlark flags.
+ if (!optionStarlarkName.startsWith(COMMAND_LINE_OPTION_PREFIX)) {
+ continue;
+ }
+ String optionNativeName = optionStarlarkName.substring(COMMAND_LINE_OPTION_PREFIX.length());
+ OptionInfo optionInfo = optionToFragment.get(optionNativeName);
+ // A null optionInfo means the flag is invalid. Starlark transitions independently catch and
+ // report that (search the code for "do not correspond to valid settings").
+ if (optionInfo != null) {
+ fragments.add(optionInfo.getOptionClass());
+ }
+ }
+ return fragments.build();
+ }
+
/** Exception class for exceptions thrown during application of a starlark-defined transition */
// TODO(juliexxia): add more information to this exception e.g. originating target of transition
public static class TransitionException extends Exception {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index 57ed3fb..31ecaf9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -28,6 +28,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
@@ -35,7 +36,9 @@
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
+import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.HostTransition;
import com.google.devtools.build.lib.analysis.config.TransitionFactories;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
@@ -231,7 +234,7 @@
/** Android Split configuration transition for properly handling native dependencies */
public static final class AndroidSplitTransition
implements SplitTransition, AndroidSplitTransititionApi {
- private static void setCrosstoolToAndroid(BuildOptions options) {
+ private static void setCrosstoolToAndroid(BuildOptionsView options) {
AndroidConfiguration.Options androidOptions = options.get(AndroidConfiguration.Options.class);
CppOptions cppOptions = options.get(CppOptions.class);
@@ -243,8 +246,17 @@
}
@Override
+ public ImmutableSet<Class<? extends FragmentOptions>> requiresOptionFragments() {
+ return ImmutableSet.of(
+ AndroidConfiguration.Options.class,
+ CoreOptions.class,
+ CppOptions.class,
+ PlatformOptions.class);
+ }
+
+ @Override
public ImmutableMap<String, BuildOptions> split(
- BuildOptions buildOptions, EventHandler eventHandler) {
+ BuildOptionsView buildOptions, EventHandler eventHandler) {
AndroidConfiguration.Options androidOptions =
buildOptions.get(AndroidConfiguration.Options.class);
@@ -256,21 +268,22 @@
if (androidOptions.cpu.isEmpty()
|| androidCrosstoolTop == null
|| androidCrosstoolTop.equals(cppOptions.crosstoolTop)) {
- return ImmutableMap.of(buildOptions.get(CoreOptions.class).cpu, buildOptions);
+ return ImmutableMap.of(
+ buildOptions.get(CoreOptions.class).cpu, buildOptions.underlying());
} else {
- BuildOptions splitOptions = buildOptions.clone();
+ BuildOptionsView splitOptions = buildOptions.clone();
splitOptions.get(CoreOptions.class).cpu = androidOptions.cpu;
setCommonAndroidOptions(androidOptions, splitOptions);
- return ImmutableMap.of(androidOptions.cpu, splitOptions);
+ return ImmutableMap.of(androidOptions.cpu, splitOptions.underlying());
}
} else {
ImmutableMap.Builder<String, BuildOptions> result = ImmutableMap.builder();
for (String cpu : ImmutableSortedSet.copyOf(androidOptions.fatApkCpus)) {
- BuildOptions splitOptions = buildOptions.clone();
+ BuildOptionsView splitOptions = buildOptions.clone();
// Disable fat APKs for the child configurations.
splitOptions.get(AndroidConfiguration.Options.class).fatApkCpus = ImmutableList.of();
@@ -279,14 +292,14 @@
splitOptions.get(AndroidConfiguration.Options.class).cpu = cpu;
splitOptions.get(CoreOptions.class).cpu = cpu;
setCommonAndroidOptions(androidOptions, splitOptions);
- result.put(cpu, splitOptions);
+ result.put(cpu, splitOptions.underlying());
}
return result.build();
}
}
private void setCommonAndroidOptions(
- AndroidConfiguration.Options androidOptions, BuildOptions newOptions) {
+ AndroidConfiguration.Options androidOptions, BuildOptionsView newOptions) {
newOptions.get(CppOptions.class).cppCompiler = androidOptions.cppCompiler;
newOptions.get(CppOptions.class).libcTopLabel = androidOptions.androidLibcTopLabel;
newOptions.get(CppOptions.class).dynamicMode = androidOptions.dynamicMode;
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/CircularDependencyTest.java b/src/test/java/com/google/devtools/build/lib/analysis/CircularDependencyTest.java
index 47f1fcb..077af5b 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/CircularDependencyTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/CircularDependencyTest.java
@@ -23,9 +23,12 @@
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
+import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
@@ -268,17 +271,24 @@
@Override
public SplitTransition create(AttributeTransitionData data) {
return new SplitTransition() {
+
+ @Override
+ public ImmutableSet<Class<? extends FragmentOptions>>
+ requiresOptionFragments() {
+ return ImmutableSet.of(CoreOptions.class);
+ }
+
@Override
public Map<String, BuildOptions> split(
- BuildOptions options, EventHandler eventHandler) {
+ BuildOptionsView options, EventHandler eventHandler) {
String define = data.attributes().get("define", STRING);
- BuildOptions newOptions = options.clone();
+ BuildOptionsView newOptions = options.clone();
CoreOptions optionsFragment = newOptions.get(CoreOptions.class);
optionsFragment.commandLineBuildVariables =
optionsFragment.commandLineBuildVariables.stream()
.filter((pair) -> !pair.getKey().equals(define))
.collect(toImmutableList());
- return ImmutableMap.of("define_cleaner", newOptions);
+ return ImmutableMap.of("define_cleaner", newOptions.underlying());
}
};
}
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 7206364..012886b 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
@@ -25,13 +25,19 @@
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.StarlarkRuleTransitionProviderTest.DummyTestLoader;
import com.google.devtools.build.lib.analysis.config.CoreOptions;
+import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.test.TestConfiguration.TestOptions;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.AttributeTransitionData;
+import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.Provider;
+import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.StarlarkProvider;
import com.google.devtools.build.lib.packages.StructImpl;
import com.google.devtools.build.lib.packages.util.BazelMockAndroidSupport;
+import com.google.devtools.build.lib.rules.cpp.CppOptions;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.build.lib.util.Fingerprint;
@@ -1795,6 +1801,52 @@
}
@Test
+ public void starlarkSplitTransitionRequiredFragments() throws Exception {
+ // All Starlark rule transitions are patch transitions, while all Starlark attribute transitions
+ // are split transitions.
+ writeAllowlistFile();
+ scratch.file(
+ "test/my_rule.bzl",
+ "load('//myinfo:myinfo.bzl', 'MyInfo')",
+ "def transition_func(settings, attr):",
+ " return [",
+ " {'//command_line_option:copt': []}", // --copt is a C++ option.
+ " ]",
+ "my_transition = transition(",
+ " implementation = transition_func,",
+ " inputs = [],",
+ " outputs = ['//command_line_option:copt'])",
+ "def impl(ctx): ",
+ " return []",
+ "my_rule = rule(",
+ " implementation = impl,",
+ " attrs = {",
+ " 'dep': attr.label(cfg = my_transition),",
+ " '_whitelist_function_transition': attr.label(",
+ " default = '//tools/whitelists/function_transition_whitelist',",
+ " ),",
+ " })");
+ scratch.file(
+ "test/BUILD",
+ "load('//test:my_rule.bzl', 'my_rule')",
+ "my_rule(name = 'test', dep = ':dep')",
+ "cc_library(name = 'dep', srcs = ['dep.c'])");
+
+ ConfiguredTargetAndData ct = getConfiguredTargetAndData("//test");
+ assertNoEvents();
+ Rule testTarget = (Rule) ct.getTarget();
+ ConfiguredAttributeMapper attributes =
+ ConfiguredAttributeMapper.of(testTarget, ImmutableMap.of());
+ ConfigurationTransition attrTransition =
+ attributes
+ .getAttributeDefinition("dep")
+ .getTransitionFactory()
+ .create(AttributeTransitionData.builder().attributes(attributes).build());
+ assertThat(attrTransition.requiresOptionFragments(ct.getConfiguration().getOptions()))
+ .containsExactly(CppOptions.class);
+ }
+
+ @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 6f00086..e84713d 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
@@ -24,10 +24,13 @@
import com.google.devtools.build.lib.analysis.config.Fragment;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
+import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
import com.google.devtools.build.lib.analysis.test.TestConfiguration.TestOptions;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.cpp.CppOptions;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionDocumentationCategory;
@@ -1366,4 +1369,43 @@
assertNoEvents();
assertThat(getConfiguration(ct).getOptions().get(CppOptions.class).fissionModes).isEmpty();
}
+
+ @Test
+ public void starlarkPatchTransitionRequiredFragments() throws Exception {
+ // All Starlark rule transitions are patch transitions, while all Starlark attribute transitions
+ // are split transitions.
+ writeAllowlistFile();
+ scratch.file(
+ "test/transitions.bzl",
+ "def _impl(settings, attr):",
+ " return {'//command_line_option:copt': []}", // --copt is a C++ option.
+ "my_transition = transition(implementation = _impl, inputs = [],",
+ " outputs = ['//command_line_option:copt'])");
+ scratch.file(
+ "test/rules.bzl",
+ "load('//test:transitions.bzl', 'my_transition')",
+ "def _impl(ctx):",
+ " return []",
+ "my_rule = rule(",
+ " implementation = _impl,",
+ " cfg = my_transition,",
+ " attrs = {",
+ " '_whitelist_function_transition': attr.label(",
+ " default = '//tools/whitelists/function_transition_whitelist',",
+ " ),",
+ " })");
+ scratch.file(
+ "test/BUILD",
+ "load('//test:rules.bzl', 'my_rule')",
+ "platform(name = 'my_platform')",
+ "my_rule(name = 'test')");
+
+ ConfiguredTargetAndData ct = getConfiguredTargetAndData("//test");
+ assertNoEvents();
+ Rule testTarget = (Rule) ct.getTarget();
+ ConfigurationTransition ruleTransition =
+ testTarget.getRuleClassObject().getTransitionFactory().create(testTarget);
+ assertThat(ruleTransition.requiresOptionFragments(ct.getConfiguration().getOptions()))
+ .containsExactly(CppOptions.class);
+ }
}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/config/TransitionFactoriesTest.java b/src/test/java/com/google/devtools/build/lib/analysis/config/TransitionFactoriesTest.java
index 67dcf08..3c00b5b 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/config/TransitionFactoriesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/config/TransitionFactoriesTest.java
@@ -20,8 +20,6 @@
import com.google.devtools.build.lib.analysis.config.transitions.NullTransition;
import com.google.devtools.build.lib.analysis.config.transitions.SplitTransition;
import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory;
-import com.google.devtools.build.lib.events.EventHandler;
-import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -61,13 +59,9 @@
public void splitTransition() {
TransitionFactory<Object> factory =
TransitionFactories.of(
- new SplitTransition() {
- @Override
- public Map<String, BuildOptions> split(
- BuildOptions buildOptions, EventHandler eventHandler) {
- return ImmutableMap.of("test0", buildOptions.clone());
- }
- });
+ (SplitTransition)
+ (buildOptions, eventHandler) ->
+ ImmutableMap.of("test0", buildOptions.clone().underlying()));
assertThat(factory).isNotNull();
assertThat(factory.isHost()).isFalse();
assertThat(factory.isSplit()).isTrue();