aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/config
diff options
context:
space:
mode:
authorGravatar gregce <gregce@google.com>2017-07-06 18:44:38 -0400
committerGravatar John Cater <jcater@google.com>2017-07-07 07:08:19 -0400
commit490b0956e6cc8449072f3010c5197d9d6c621d09 (patch)
tree93e46e560d7ba8cb974e2a87124282056a9e5ff5 /src/main/java/com/google/devtools/build/lib/analysis/config
parent5ba65a5c00f18a5ebd677ce10693b453736915f9 (diff)
Factor out BuildConfigurationCollection.Transitions.getDynamicTransition.
This is a legacy dependency on the configuration transition table, which is only needed for static configurations. Dynamic configurations didn't actually use anything in that table: this was just a convenience interface that could have equally been defined somewhere else. So this cl defines it somewhere else. There's still one last dependency: Transitions.configurationHook. We'll tackle that in a followup cl. PiperOrigin-RevId: 161141650
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/config')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java50
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfigurationCollection.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/DynamicTransitionMapper.java88
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());
+ }
+}