diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/config')
4 files changed, 115 insertions, 39 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index 8c217afa17..4e33c0ffbe 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -1204,7 +1204,7 @@ public final class BuildConfiguration implements BuildEvent { private final ImmutableMap<Class<? extends Fragment>, Fragment> fragments; private final ImmutableMap<String, Class<? extends Fragment>> skylarkVisibleFragments; private final RepositoryName mainRepositoryName; - + private final DynamicTransitionMapper dynamicTransitionMapper; /** * Directories in the output tree. @@ -1516,11 +1516,15 @@ public final class BuildConfiguration implements BuildEvent { /** * Constructs a new BuildConfiguration instance. + * + * <p>Callers that pass null for {@code dynamicTransitionMapper} should not use dynamic + * configurations. */ public BuildConfiguration(BlazeDirectories directories, Map<Class<? extends Fragment>, Fragment> fragmentsMap, BuildOptions buildOptions, - String repositoryName) { + String repositoryName, + @Nullable DynamicTransitionMapper dynamicTransitionMapper) { this.directories = directories; this.fragments = ImmutableSortedMap.copyOf(fragmentsMap, lexicalFragmentSorter); @@ -1530,6 +1534,7 @@ public final class BuildConfiguration implements BuildEvent { this.actionsEnabled = buildOptions.enableActions(); this.options = buildOptions.get(Options.class); this.mainRepositoryName = RepositoryName.createFromValidStrippedName(repositoryName); + this.dynamicTransitionMapper = dynamicTransitionMapper; // We can't use an ImmutableMap.Builder here; we need the ability to add entries with keys that // are already in the map so that the same define can be specified on the command line twice, @@ -1612,8 +1617,13 @@ public final class BuildConfiguration implements BuildEvent { } BuildOptions options = buildOptions.trim( getOptionsClasses(fragmentsMap.keySet(), ruleClassProvider)); - BuildConfiguration newConfig = new BuildConfiguration( - directories, fragmentsMap, options, mainRepositoryName.strippedName()); + BuildConfiguration newConfig = + new BuildConfiguration( + directories, + fragmentsMap, + options, + mainRepositoryName.strippedName(), + dynamicTransitionMapper); newConfig.setConfigurationTransitions(this.transitions); return newConfig; } @@ -1777,12 +1787,6 @@ public final class BuildConfiguration implements BuildEvent { */ public interface TransitionApplier { /** - * Creates a new instance of this transition applier bound to the specified source - * configuration. - */ - TransitionApplier create(BuildConfiguration config); - - /** * Accepts the given configuration transition. The implementation decides how to turn * this into an actual configuration. This may be called multiple times (representing a * request for a sequence of transitions). @@ -1838,11 +1842,6 @@ public final class BuildConfiguration implements BuildEvent { } @Override - public TransitionApplier create(BuildConfiguration configuration) { - return new StaticTransitionApplier(configuration); - } - - @Override public void applyTransition(Transition transition) { if (transition == Attribute.ConfigurationTransition.NULL) { toConfigurations = Lists.<BuildConfiguration>asList(null, new BuildConfiguration[0]); @@ -1922,8 +1921,8 @@ public final class BuildConfiguration implements BuildEvent { * transitions that the caller subsequently creates configurations from. */ private static class DynamicTransitionApplier implements TransitionApplier { - private final BuildOptions originalOptions; private final Transitions transitionsManager; + private final DynamicTransitionMapper dynamicTransitionMapper; private boolean splitApplied = false; // The transition this applier applies to dep rules. When multiple transitions are requested, @@ -1931,14 +1930,10 @@ public final class BuildConfiguration implements BuildEvent { // so calling code doesn't need special logic to support combinations. private Transition currentTransition = Attribute.ConfigurationTransition.NONE; - private DynamicTransitionApplier(BuildConfiguration originalConfiguration) { - this.originalOptions = originalConfiguration.getOptions(); - this.transitionsManager = originalConfiguration.getTransitions(); - } - - @Override - public TransitionApplier create(BuildConfiguration configuration) { - return new DynamicTransitionApplier(configuration); + private DynamicTransitionApplier(Transitions transitionsManager, + DynamicTransitionMapper dynamicTransitionMapper) { + this.transitionsManager = transitionsManager; + this.dynamicTransitionMapper = dynamicTransitionMapper; } /** @@ -1973,10 +1968,9 @@ public final class BuildConfiguration implements BuildEvent { // in the last segment of a ComposingSplitTransition, those optimizations wouldn't trigger. return HostTransition.INSTANCE; } + // TODO(gregce): remove this dynamic transition mapping when static configs are removed. - Transition dynamicTransition = (transition2 instanceof PatchTransition) - ? transition2 - : transitionsManager.getDynamicTransition(transition2); + Transition dynamicTransition = dynamicTransitionMapper.map(transition2); return transition1 == Attribute.ConfigurationTransition.NONE ? dynamicTransition : new ComposingSplitTransition(transition1, dynamicTransition); @@ -2101,7 +2095,7 @@ public final class BuildConfiguration implements BuildEvent { */ public TransitionApplier getTransitionApplier() { return useDynamicConfigurations() - ? new DynamicTransitionApplier(this) + ? new DynamicTransitionApplier(this.getTransitions(), dynamicTransitionMapper) : new StaticTransitionApplier(this); } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationCollection.java index 935fb978cb..1137280bde 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationCollection.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationCollection.java @@ -260,17 +260,11 @@ public final class BuildConfigurationCollection { * in which they must co-exist. Once dynamic configurations are production-ready, we'll remove * the static configuration code entirely. */ + @Deprecated public Transition getDynamicTransition(Transition transition) { - Preconditions.checkState(configuration.useDynamicConfigurations()); - if (transition == Attribute.ConfigurationTransition.NONE) { - return transition; - } else if (transition == Attribute.ConfigurationTransition.NULL) { - return transition; - } else if (transition == Attribute.ConfigurationTransition.HOST) { - return HostTransition.INSTANCE; - } else { - throw new UnsupportedOperationException("No dynamic mapping for " + transition.toString()); - } + // Keep this interface for now because some other dead code is still calling it. + throw new UnsupportedOperationException( + "This interface is no longer supported and will be removed soon."); } /** diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java index 3a95a4bb0f..0080786b97 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java @@ -110,7 +110,7 @@ public final class ConfigurationFactory { return null; } - result = new BuildConfiguration(directories, fragments, buildOptions, repositoryName); + result = new BuildConfiguration(directories, fragments, buildOptions, repositoryName, null); cache.put(cacheKey, result); return result; } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/DynamicTransitionMapper.java b/src/main/java/com/google/devtools/build/lib/analysis/config/DynamicTransitionMapper.java new file mode 100644 index 0000000000..1f3a78b46b --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/DynamicTransitionMapper.java @@ -0,0 +1,88 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.analysis.config; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.packages.Attribute; +import com.google.devtools.build.lib.packages.Attribute.Transition; +import com.google.devtools.build.lib.packages.RuleClass; + +/** + * Maps non-{@link PatchTransition} declarations to their implementable equivalents. + * + * <p>Blaze applies configuration transitions by executing {@link PatchTransition} instances. But + * for legacy reasons, not every transition declaration is a {@link PatchTransition}. The most + * prominent example is {@link Attribute.ConfigurationTransition}, which defines its transitions as + * enums. These transitions are used all over the place. So we need a way to continue to support + * them. + * + * <p>Hence this class. + * + * <p>Going forward, we should eliminate the need for this class by eliminating + * non-{@link PatchTransition} transitions. This is conceptually straightforward: replace + * declarations of the form {@link RuleClass.Builder#cfg(Transition)} with + * {@link RuleClass.Builder#cfg(PatchTransition)}. That way, transition declarations "just work", + * with no extra fuss. But this is a migration that will take some time to complete. + * + * {@link Attribute.ConfigurationTransition#DATA} provides the most complicated challenge. This is + * C++/LIPO logic, and the implementation is in C++ rule code + * ({@link com.google.devtools.build.lib.rules.cpp.transitions.DisableLipoTransition}). But the enum + * is defined in {@link Attribute}, which is in {@code lib.packages}, which has access to neither + * rule-specific nor configuration-specific code. Furthermore, many non-C++ rules declare this + * transition. We ultimately need a cleaner way to inject this rules-specific logic into general + * Blaze code. + */ +public final class DynamicTransitionMapper { + /** + * Use this to declare a no-op transition that keeps the input configuration. + */ + public static final Transition SELF = () -> { + throw new UnsupportedOperationException("This is just an alias for \"keep the input " + + "configuration\". It shouldn't actually apply a real transition"); + }; + + private final ImmutableMap<Transition, Transition> map; + + /** + * Creates a new mapper with the given mapping. Any transition not in this mapping triggers + * an {@link IllegalArgumentException}. + */ + public DynamicTransitionMapper(ImmutableMap<Transition, Transition> map) { + this.map = map; + } + + /** + * Given an input transition, returns the equivalent transition Blaze's implementation logic knows + * how to apply. + * + * <p>When the input is a {@link PatchTransition}, this just returns the input. This is because + * that's the kind of transition that Blaze natively applies. For this reason, all inputs should + * ideally be {@link PatchTransition}s. + * + * <p>Non-{@link PatchTransition} inputs that aren't mapped here throw an + * {@link IllegalArgumentException}. + */ + public Transition map(Transition fromTransition) { + if (fromTransition instanceof PatchTransition) { + return fromTransition; + } + Transition toTransition = map.get(fromTransition); + if (toTransition == SELF) { + return fromTransition; + } else if (toTransition != null) { + return toTransition; + } + throw new IllegalArgumentException("No dynamic mapping for " + fromTransition.toString()); + } +} |