aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
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
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')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java22
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java23
-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
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java17
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java3
13 files changed, 205 insertions, 61 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java
index 8739918377..2396c3edbb 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BaseRuleClasses.java
@@ -29,14 +29,19 @@ import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
+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.DynamicTransitionMapper;
+import com.google.devtools.build.lib.analysis.config.HostTransition;
+import com.google.devtools.build.lib.analysis.config.PatchTransition;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.analysis.constraints.EnvironmentRule;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabelList;
+import com.google.devtools.build.lib.packages.Attribute.Transition;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass;
@@ -327,4 +332,21 @@ public class BaseRuleClasses {
.build();
}
}
+
+ /**
+ * Declares the implementations for {@link Attribute.ConfigurationTransition} enums.
+ *
+ * <p>We can't put this in {@link Attribute} because that's in the {@code lib.packages} package,
+ * which has no access to configuration classes.
+ *
+ * <p>New transitions should extend {@link PatchTransition}, which avoids the need for this map.
+ */
+ public static final ImmutableMap<Transition, Transition> DYNAMIC_TRANSITIONS_MAP =
+ ImmutableMap.of(
+ Attribute.ConfigurationTransition.NONE, DynamicTransitionMapper.SELF,
+ Attribute.ConfigurationTransition.NULL, DynamicTransitionMapper.SELF,
+ Attribute.ConfigurationTransition.HOST, HostTransition.INSTANCE
+ // Attribute.ConfigurationTransition.DATA is skipped because it's C++-specific.
+ // The C++ rule definitions handle its mapping.
+ );
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index ac5b483a22..3b7b335e52 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -31,6 +31,7 @@ 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.ConfigurationFragmentFactory;
import com.google.devtools.build.lib.analysis.config.DefaultsPackage;
+import com.google.devtools.build.lib.analysis.config.DynamicTransitionMapper;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
@@ -214,6 +215,8 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
private final Digraph<Class<? extends RuleDefinition>> dependencyGraph =
new Digraph<>();
private ConfigurationCollectionFactory configurationCollectionFactory;
+ private ImmutableMap.Builder<Attribute.Transition, Attribute.Transition> dynamicTransitionMaps
+ = ImmutableMap.builder();
private Class<? extends BuildConfiguration.Fragment> universalFragment;
private PrerequisiteValidator prerequisiteValidator;
private ImmutableMap.Builder<String, Object> skylarkAccessibleTopLevels =
@@ -320,6 +323,11 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
return this;
}
+ public Builder addDynamicTransitionMaps(Map<Attribute.Transition, Attribute.Transition> maps) {
+ dynamicTransitionMaps.putAll(maps);
+ return this;
+ }
+
public Builder setUniversalConfigurationFragment(
Class<? extends BuildConfiguration.Fragment> fragment) {
this.universalFragment = fragment;
@@ -429,6 +437,7 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
ImmutableList.copyOf(configurationOptions),
ImmutableList.copyOf(configurationFragmentFactories),
configurationCollectionFactory,
+ new DynamicTransitionMapper(dynamicTransitionMaps.build()),
universalFragment,
prerequisiteValidator,
skylarkAccessibleTopLevels.build(),
@@ -529,6 +538,11 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
private final ConfigurationCollectionFactory configurationCollectionFactory;
/**
+ * The dynamic configuration transition mapper.
+ */
+ private final DynamicTransitionMapper dynamicTransitionMapper;
+
+ /**
* A configuration fragment that should be available to all rules even when they don't
* explicitly require it.
*/
@@ -554,6 +568,7 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
ImmutableList<Class<? extends FragmentOptions>> configurationOptions,
ImmutableList<ConfigurationFragmentFactory> configurationFragments,
ConfigurationCollectionFactory configurationCollectionFactory,
+ DynamicTransitionMapper dynamicTransitionMapper,
Class<? extends BuildConfiguration.Fragment> universalFragment,
PrerequisiteValidator prerequisiteValidator,
ImmutableMap<String, Object> skylarkAccessibleJavaClasses,
@@ -571,6 +586,7 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
this.configurationOptions = configurationOptions;
this.configurationFragmentFactories = configurationFragments;
this.configurationCollectionFactory = configurationCollectionFactory;
+ this.dynamicTransitionMapper = dynamicTransitionMapper;
this.universalFragment = universalFragment;
this.prerequisiteValidator = prerequisiteValidator;
this.globals = createGlobals(skylarkAccessibleJavaClasses, skylarkModules);
@@ -650,6 +666,13 @@ public class ConfiguredRuleClassProvider implements RuleClassProvider {
}
/**
+ * Returns the dynamic configuration transition mapper.
+ */
+ public DynamicTransitionMapper getDynamicTransitionMapper() {
+ return dynamicTransitionMapper;
+ }
+
+ /**
* Returns the configuration fragment that should be available to all rules even when they
* don't explicitly require it.
*/
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());
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
index cd11d56728..cf84854868 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelConfigurationCollection.java
@@ -100,12 +100,11 @@ public class BazelConfigurationCollection implements ConfigurationCollectionFact
}
@Override
+ @Deprecated
public Transition getDynamicTransition(Transition configurationTransition) {
- if (configurationTransition == ConfigurationTransition.DATA) {
- return ConfigurationTransition.NONE;
- } else {
- return super.getDynamicTransition(configurationTransition);
- }
+ // 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/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index 1f68faa6b2..5dac663dce 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -106,6 +106,7 @@ import com.google.devtools.build.lib.rules.cpp.CcToolchainSuiteRule;
import com.google.devtools.build.lib.rules.cpp.CppBuildInfo;
import com.google.devtools.build.lib.rules.cpp.CppConfigurationLoader;
import com.google.devtools.build.lib.rules.cpp.CppOptions;
+import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.proto.CcProtoAspect;
import com.google.devtools.build.lib.rules.cpp.proto.CcProtoLibraryRule;
import com.google.devtools.build.lib.rules.extra.ActionListenerRule;
@@ -233,6 +234,7 @@ public class BazelRuleClassProvider {
public void init(Builder builder) {
builder.addConfigurationOptions(FeaturePolicyOptions.class);
builder.addConfigurationFragment(new FeaturePolicyLoader(FEATURE_POLICY_FEATURES));
+ builder.addDynamicTransitionMaps(BaseRuleClasses.DYNAMIC_TRANSITIONS_MAP);
builder.addRuleDefinition(new BaseRuleClasses.RootRule());
builder.addRuleDefinition(new BaseRuleClasses.BaseRule());
@@ -381,6 +383,7 @@ public class BazelRuleClassProvider {
CppOptions.class, new CppConfigurationLoader(Functions.<String>identity()));
builder.addBuildInfoFactory(new CppBuildInfo());
+ builder.addDynamicTransitionMaps(CppRuleClasses.DYNAMIC_TRANSITIONS_MAP);
builder.addRuleDefinition(new CcToolchainRule());
builder.addRuleDefinition(new CcToolchainSuiteRule());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
index 4ad604ed55..a8b2f3ed35 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppRuleClasses.java
@@ -30,8 +30,10 @@ import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.PIC_OBJECT_FI
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.SHARED_LIBRARY;
import static com.google.devtools.build.lib.rules.cpp.CppFileTypes.VERSIONED_SHARED_LIBRARY;
+import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.LanguageDependentFragment.LibraryLanguage;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.PatchTransition;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
@@ -40,7 +42,9 @@ import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleTransitionFactory;
+import com.google.devtools.build.lib.rules.cpp.transitions.DisableLipoTransition;
import com.google.devtools.build.lib.rules.cpp.transitions.EnableLipoTransition;
+import com.google.devtools.build.lib.rules.cpp.transitions.LipoContextCollectorTransition;
import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec;
import com.google.devtools.build.lib.util.FileTypeSet;
@@ -87,6 +91,19 @@ public class CppRuleClasses {
}
/**
+ * Declares the implementations for C++ transition enums.
+ *
+ * <p>New transitions should extend {@link PatchTransition}, which avoids the need for this map.
+ */
+ public static final ImmutableMap<Transition, Transition> DYNAMIC_TRANSITIONS_MAP =
+ ImmutableMap.of(
+ Attribute.ConfigurationTransition.DATA, DisableLipoTransition.INSTANCE,
+ LipoTransition.LIPO_COLLECTOR, LipoContextCollectorTransition.INSTANCE
+ // TARGET_CONFIG_FOR_LIPO has no entry because only static configurations use it.
+ );
+
+
+ /**
* Rule transition factory that enables LIPO on the LIPO context binary (i.e. applies a DATA ->
* TARGET transition).
*
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
index b515fd7ce4..be1354bf79 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/BuildConfigurationFunction.java
@@ -39,15 +39,14 @@ import java.util.Set;
public class BuildConfigurationFunction implements SkyFunction {
private final BlazeDirectories directories;
- private final RuleClassProvider ruleClassProvider;
+ private final ConfiguredRuleClassProvider ruleClassProvider;
private final ConfigurationCollectionFactory collectionFactory;
public BuildConfigurationFunction(BlazeDirectories directories,
RuleClassProvider ruleClassProvider) {
this.directories = directories;
- this.ruleClassProvider = ruleClassProvider;
- collectionFactory =
- ((ConfiguredRuleClassProvider) ruleClassProvider).getConfigurationCollectionFactory();
+ this.ruleClassProvider = (ConfiguredRuleClassProvider) ruleClassProvider;
+ collectionFactory = this.ruleClassProvider.getConfigurationCollectionFactory();
}
@Override
@@ -75,14 +74,17 @@ public class BuildConfigurationFunction implements SkyFunction {
fragmentsMap.put(fragment.getClass(), fragment);
}
- BuildConfiguration config = new BuildConfiguration(directories, fragmentsMap,
- key.getBuildOptions(), workspaceNameValue.getName());
+ BuildConfiguration config =
+ new BuildConfiguration(
+ directories,
+ fragmentsMap,
+ key.getBuildOptions(),
+ workspaceNameValue.getName(),
+ ruleClassProvider.getDynamicTransitionMapper());
// Unlike static configurations, dynamic configurations don't need to embed transition logic
- // within the configuration itself. However we still use this interface to provide a mapping
- // between Transition types (e.g. HOST) and the dynamic transitions that apply those
- // transitions. Once static configurations are cleaned out we won't need this interface
- // any more (all the centralized logic that maintains the transition logic can be distributed
- // to the actual rule code that uses it).
+ // in the configuration itself. However we still use this interface to supply
+ // BuildConfigurationCollection.Transitions.configurationHook. Once we remove that dependency
+ // we can remove the below completely.
config.setConfigurationTransitions(collectionFactory.getDynamicTransitionLogic(config));
return new BuildConfigurationValue(config);
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
index 3bf6102e58..84c83395f5 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java
@@ -1114,8 +1114,10 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory {
// The host configuration inherits the data, not target options. This is so host tools don't
// apply LIPO.
BuildConfiguration firstTargetConfig = topLevelTargetConfigs.get(0);
- Attribute.Transition dataTransition = firstTargetConfig.getTransitions()
- .getDynamicTransition(Attribute.ConfigurationTransition.DATA);
+ Attribute.Transition dataTransition =
+ ((ConfiguredRuleClassProvider) ruleClassProvider)
+ .getDynamicTransitionMapper()
+ .map(Attribute.ConfigurationTransition.DATA);
BuildOptions dataOptions = dataTransition != Attribute.ConfigurationTransition.NONE
? ((PatchTransition) dataTransition).apply(firstTargetConfig.getOptions())
: firstTargetConfig.getOptions();
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
index d8e079ea11..81db738b73 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/BuildViewTestCase.java
@@ -1494,9 +1494,8 @@ public abstract class BuildViewTestCase extends FoundationTestCase {
} else if (!fromConfig.useDynamicConfigurations()) {
return fromConfig.getConfiguration(transition);
} else {
- PatchTransition patchTransition = (transition instanceof PatchTransition)
- ? (PatchTransition) transition
- : (PatchTransition) fromConfig.getTransitions().getDynamicTransition(transition);
+ PatchTransition patchTransition =
+ (PatchTransition) ruleClassProvider.getDynamicTransitionMapper().map(transition);
return skyframeExecutor.getConfigurationForTesting(reporter, fromConfig.fragmentClasses(),
patchTransition.apply(fromConfig.getOptions()));
}
diff --git a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
index 9fae49273a..a3b5b7e4e1 100644
--- a/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/runtime/BuildEventStreamerTest.java
@@ -608,7 +608,8 @@ public class BuildEventStreamerTest extends FoundationTestCase {
BuildConfiguration.Fragment>of(),
BuildOptions.of(ImmutableList.<Class<? extends FragmentOptions>>of(
BuildConfiguration.Options.class)),
- "workspace");
+ "workspace",
+ null);
BuildEvent firstWithConfiguration =
new GenericConfigurationEvent(testId("first"), configuration);
BuildEvent secondWithConfiguration =