diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/config')
5 files changed, 68 insertions, 18 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java index 531c6f120e..f26ca9f920 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java @@ -429,7 +429,7 @@ public final class ConfigurationResolver { // TODO(bazel-team): safety-check that this never mutates fromOptions. result = ImmutableList.of(((PatchTransition) transition).patch(fromOptions)); } else if (transition instanceof SplitTransition) { - return ((SplitTransition) transition).checkedSplit(fromOptions); + return ((SplitTransition) transition).split(fromOptions); } else { throw new IllegalStateException(String.format( "unsupported config transition type: %s", transition.getClass().getName())); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ComposingSplitTransition.java b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ComposingSplitTransition.java index 71e377038e..190b867329 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ComposingSplitTransition.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/transitions/ComposingSplitTransition.java @@ -120,7 +120,7 @@ public class ComposingSplitTransition implements SplitTransition { if (transition instanceof PatchTransition) { return ImmutableList.<BuildOptions>of(((PatchTransition) transition).patch(fromOptions)); } else if (transition instanceof SplitTransition) { - return ((SplitTransition) transition).checkedSplit(fromOptions); + return ((SplitTransition) transition).split(fromOptions); } else { throw new IllegalStateException( String.format("Unsupported composite transition type: %s", 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 3c6f5b94c8..8995bf63f5 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 @@ -14,11 +14,35 @@ package com.google.devtools.build.lib.analysis.config.transitions; +import com.google.devtools.build.lib.analysis.config.BuildOptions; +import java.util.List; + /** * A configuration transition. */ public interface ConfigurationTransition { /** + * Returns the list of {@code BuildOptions} after applying this transition. + * + * <p>Returning an empty or null list triggers a {@link RuntimeException}. + */ + List<BuildOptions> apply(BuildOptions buildOptions); + + /** + * We want to keep the number of transition interfaces no larger than what's necessary to + * maintain a clear configuration API. + * + * <p>This method provides a speed bump against creating new interfaces too casually. While we + * could provide stronger enforcement by making {@link ConfigurationTransition} an abstract class + * with a limited access constructor, keeping it as an interface supports definining transitions + * with lambdas. + * + * <p>If you're considering adding a new override, contact bazel-dev@googlegroups.com to discuss. + */ + @SuppressWarnings("unused") + String reasonForOverride(); + + /** * Does this transition switch to a "host" configuration? */ default boolean isHostTransition() { 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 1fdfa95fd3..b04b167643 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 @@ -13,10 +13,16 @@ // limitations under the License. package com.google.devtools.build.lib.analysis.config.transitions; +import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.analysis.config.BuildOptions; +import java.util.List; /** - * Interface for a configuration transition. + * A configuration transition that maps a single input {@link BuildOptions} to a single output + * {@link BuildOptions}. + * + * <p>Also see {@link SplitTransition}, which maps a single input {@link BuildOptions} to possibly + * multiple {@link BuildOptions}. * * <p>The concept is simple: given the input configuration's build options, the * transition does whatever it wants to them and returns the modified result. @@ -48,14 +54,24 @@ import com.google.devtools.build.lib.analysis.config.BuildOptions; * {@link com.google.devtools.build.lib.analysis.config.BuildOptions} doesn't currently * enforce immutability. So care must be taken not to modify the wrong instance. */ +@FunctionalInterface public interface PatchTransition extends ConfigurationTransition { - /** * Applies the transition. * - * @param options the options representing the input configuration to this transition. DO NOT - * MODIFY THIS VARIABLE WITHOUT CLONING IT FIRST. + * @param options the options representing the input configuration to this transition. <b>DO NOT + * MODIFY THIS VARIABLE WITHOUT CLONING IT FIRST!</b> * @return the options representing the desired post-transition configuration */ BuildOptions patch(BuildOptions options); + + @Override + default List<BuildOptions> apply(BuildOptions buildOptions) { + return ImmutableList.of(patch(buildOptions)); + } + + @Override + default String reasonForOverride() { + return "This is a fundamental transition modeling the simple, common case 1-1 options mapping"; + } } 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 eb71869379..525269cf2e 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 @@ -21,9 +21,16 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety; import java.util.List; /** - * A configuration split transition; this should be used to transition to multiple configurations - * simultaneously. Note that the corresponding rule implementations must have special support to - * handle this. + * A configuration transition that maps a single input {@link BuildOptions} to possibly multiple + * output {@link BuildOptions}. This provides the ability to transition to multiple configurations + * simultaneously. + * + * <p>Also see {@link PatchTransition}, which maps a single input {@BuildOptions} to a single + * output. If your transition never needs to produce multiple outputs, you should use a + * {@link PatchTransition}. + * + * Corresponding rule implementations may require special support to handle this in an organized + * way (e.g. for determining which CPU corresponds to which dep for a multi-arch split dependency). */ @ThreadSafety.Immutable @FunctionalInterface @@ -37,21 +44,24 @@ public interface SplitTransition extends ConfigurationTransition { List<BuildOptions> split(BuildOptions buildOptions); /** - * Calls {@link #split} and throws a {@link RuntimeException} if the split output is empty. + * Returns true iff {@code option} and {@splitOptions} are equal. + * + * <p>This can be used to determine if a split is a noop. */ - default List<BuildOptions> checkedSplit(BuildOptions buildOptions) { + static boolean equals(BuildOptions options, List<BuildOptions> splitOptions) { + return splitOptions.size() == 1 && Iterables.getOnlyElement(splitOptions).equals(options); + } + + @Override + default List<BuildOptions> apply(BuildOptions buildOptions) { List<BuildOptions> splitOptions = split(buildOptions); Verify.verifyNotNull(splitOptions, "Split transition output may not be null"); Verify.verify(!splitOptions.isEmpty(), "Split transition output may not be empty"); return splitOptions; } - /** - * Returns true iff {@code option} and {@splitOptions} are equal. - * - * <p>This can be used to determine if a split is a noop. - */ - static boolean equals(BuildOptions options, List<BuildOptions> splitOptions) { - return splitOptions.size() == 1 && Iterables.getOnlyElement(splitOptions).equals(options); + @Override + default String reasonForOverride() { + return "This is a fundamental transition modeling the need for multiply configured deps"; } } |