aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar Chris Parsons <cparsons@google.com>2016-04-19 22:13:59 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-04-20 11:17:13 +0000
commit2e62c0d5ac01a2cb4a3534f73519a5ad92cef60c (patch)
treeccb56a57e7f3602c3acf9f89379062b46ad1a27e /src/main/java/com/google/devtools/build
parent66cf13874a3c8f866aeace2d59231e30ca4a5032 (diff)
Introduce SplitTransitionProvider, to determine the split transition on an attribute based on the Rule itself (the transition may thus be determined based on the values of other attributes of the rule)
-- MOS_MIGRATED_REVID=120275649
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/Attribute.java106
4 files changed, 111 insertions, 16 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index a74094e124..fe8bddc4a0 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -28,7 +28,6 @@ import com.google.devtools.build.lib.packages.AspectClass;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
-import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.EnvironmentGroup;
@@ -356,13 +355,13 @@ public abstract class DependencyResolver {
}
List<BuildConfiguration> actualConfigurations = ImmutableList.of(configuration);
- if (attribute.getConfigurationTransition() instanceof SplitTransition<?>) {
+ if (attribute.hasSplitConfigurationTransition()) {
Preconditions.checkState(attribute.getConfigurator() == null);
// TODO(bazel-team): This ends up applying the split transition twice, both here and in the
// visitRule method below - this is not currently a problem, because the configuration graph
// never contains nested split transitions, so the second application is idempotent.
- actualConfigurations = configuration.getSplitConfigurations(
- (SplitTransition<?>) attribute.getConfigurationTransition());
+ actualConfigurations =
+ configuration.getSplitConfigurations(attribute.getSplitTransition(rule));
}
for (BuildConfiguration actualConfig : actualConfigurations) {
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 0b1248c538..8d930a29e8 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -584,8 +584,7 @@ public final class RuleContext extends TargetContext
public List<? extends TransitiveInfoCollection> getPrerequisites(String attributeName,
Mode mode) {
Attribute attributeDefinition = getAttribute(attributeName);
- if ((mode == Mode.TARGET)
- && (attributeDefinition.getConfigurationTransition() instanceof SplitTransition)) {
+ if ((mode == Mode.TARGET) && (attributeDefinition.hasSplitConfigurationTransition())) {
// TODO(bazel-team): If you request a split-configured attribute in the target configuration,
// we return only the list of configured targets for the first architecture; this is for
// backwards compatibility with existing code in cases where the call to getPrerequisites is
@@ -617,8 +616,7 @@ public final class RuleContext extends TargetContext
checkAttribute(attributeName, Mode.SPLIT);
Attribute attributeDefinition = getAttribute(attributeName);
- SplitTransition<?> transition =
- (SplitTransition<?>) attributeDefinition.getConfigurationTransition();
+ SplitTransition<?> transition = attributeDefinition.getSplitTransition(rule);
List<BuildConfiguration> configurations =
getConfiguration().getTransitions().getSplitConfigurations(transition);
if (configurations.size() == 1) {
@@ -969,7 +967,7 @@ public final class RuleContext extends TargetContext
+ " is not configured for the data configuration");
}
} else if (mode == Mode.SPLIT) {
- if (!(attributeDefinition.getConfigurationTransition() instanceof SplitTransition)) {
+ if (!(attributeDefinition.hasSplitConfigurationTransition())) {
throw new IllegalStateException(getRule().getLocation() + ": "
+ getRuleClassNameForLogging() + " attribute " + attributeName
+ " is not configured for a split transition");
@@ -998,7 +996,7 @@ public final class RuleContext extends TargetContext
return Mode.TARGET;
} else if (attributeDefinition.getConfigurationTransition() == ConfigurationTransition.DATA) {
return Mode.DATA;
- } else if (attributeDefinition.getConfigurationTransition() instanceof SplitTransition) {
+ } else if (attributeDefinition.hasSplitConfigurationTransition()) {
return Mode.SPLIT;
}
throw new IllegalStateException(getRule().getLocation() + ": "
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 67e34abefc..3f8c6be31f 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
@@ -1825,9 +1825,9 @@ public final class BuildConfiguration {
return;
}
- if (attribute.getConfigurationTransition() instanceof SplitTransition) {
+ if (attribute.hasSplitConfigurationTransition()) {
Preconditions.checkState(attribute.getConfigurator() == null);
- transitionApplier.split((SplitTransition<?>) attribute.getConfigurationTransition());
+ transitionApplier.split(attribute.getSplitTransition(fromRule));
} else {
// III. Attributes determine configurations. The configuration of a prerequisite is determined
// by the attribute.
diff --git a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
index cf4d210aef..aeac774c66 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/Attribute.java
@@ -149,11 +149,27 @@ public final class Attribute implements Comparable<Attribute> {
/** Transition from the target configuration to the data configuration. */
// TODO(bazel-team): Move this elsewhere.
- DATA;
+ DATA,
+
+ /**
+ * Transition to one or more configurations. To obtain the actual child configurations,
+ * invoke {@link Attribute#getSplitTransition(Rule)}. See {@link SplitTransition}.
+ **/
+ SPLIT(true);
+
+ private boolean defaultsToSelf;
+
+ ConfigurationTransition() {
+ this(false);
+ }
+
+ ConfigurationTransition(boolean defaultsToSelf) {
+ this.defaultsToSelf = defaultsToSelf;
+ }
@Override
public boolean defaultsToSelf() {
- return false;
+ return defaultsToSelf;
}
}
@@ -270,6 +286,37 @@ public final class Attribute implements Comparable<Attribute> {
}
/**
+ * Provides a {@link SplitTransition} given the originating target {@link Rule}. The split
+ * transition may be constant for all instances of the originating rule, or it may differ
+ * based on attributes of that rule. For instance, a split transition on a rule's deps may differ
+ * depending on the 'platform' attribute of the rule.
+ */
+ public interface SplitTransitionProvider {
+ /**
+ * Returns the {@link SplitTransition} given the originating rule.
+ */
+ SplitTransition<?> apply(Rule fromRule);
+ }
+
+ /**
+ * Implementation of {@link SplitTransitionProvider} that returns a single {@link SplitTransition}
+ * regardless of the originating rule.
+ */
+ private static class BasicSplitTransitionProvider implements SplitTransitionProvider {
+
+ private final SplitTransition<?> splitTransition;
+
+ BasicSplitTransitionProvider(SplitTransition<?> splitTransition) {
+ this.splitTransition = splitTransition;
+ }
+
+ @Override
+ public SplitTransition<?> apply(Rule fromRule) {
+ return splitTransition;
+ }
+ }
+
+ /**
* A predicate class to check if the value of the attribute comes from a predefined set.
*/
public static class AllowedValueSet implements PredicateWithMessage<Object> {
@@ -340,6 +387,7 @@ public final class Attribute implements Comparable<Attribute> {
private Predicate<RuleClass> allowedRuleClassesForLabels = Predicates.alwaysTrue();
private Predicate<RuleClass> allowedRuleClassesForLabelsWarning = Predicates.alwaysFalse();
private Configurator<?, ?> configurator;
+ private SplitTransitionProvider splitTransitionProvider;
private FileTypeSet allowedFileTypesForLabels;
private ValidityPredicate validityPredicate = ANY_EDGE;
private Object value;
@@ -444,14 +492,40 @@ public final class Attribute implements Comparable<Attribute> {
}
/**
+ * Defines the configuration transition for this attribute.
+ */
+ public Builder<TYPE> cfg(SplitTransitionProvider splitTransitionProvider) {
+ Preconditions.checkState(this.configTransition == ConfigurationTransition.NONE,
+ "the configuration transition is already set");
+
+ this.splitTransitionProvider = Preconditions.checkNotNull(splitTransitionProvider);
+ this.configTransition = ConfigurationTransition.SPLIT;
+ return this;
+ }
+
+ /**
+ * Defines the configuration transition for this attribute. Defaults to
+ * {@code NONE}.
+ */
+ public Builder<TYPE> cfg(SplitTransition<?> configTransition) {
+ return cfg(new BasicSplitTransitionProvider(Preconditions.checkNotNull(configTransition)));
+ }
+
+ /**
* Defines the configuration transition for this attribute. Defaults to
* {@code NONE}.
*/
public Builder<TYPE> cfg(Transition configTransition) {
Preconditions.checkState(this.configTransition == ConfigurationTransition.NONE,
"the configuration transition is already set");
- this.configTransition = configTransition;
- return this;
+ Preconditions.checkArgument(configTransition != ConfigurationTransition.SPLIT,
+ "split transitions must be defined using the SplitTransition object");
+ if (configTransition instanceof SplitTransition) {
+ return cfg((SplitTransition<?>) configTransition);
+ } else {
+ this.configTransition = configTransition;
+ return this;
+ }
}
public Builder<TYPE> cfg(Configurator<?, ?> configurator) {
@@ -877,6 +951,7 @@ public final class Attribute implements Comparable<Attribute> {
valueSet ? value : type.getDefaultValue(),
configTransition,
configurator,
+ splitTransitionProvider,
allowedRuleClassesForLabels,
allowedRuleClassesForLabelsWarning,
allowedFileTypesForLabels,
@@ -1135,6 +1210,7 @@ public final class Attribute implements Comparable<Attribute> {
private final Transition configTransition;
private final Configurator<?, ?> configurator;
+ private final SplitTransitionProvider splitTransitionProvider;
/**
* For label or label-list attributes, this predicate returns which rule
@@ -1192,6 +1268,7 @@ public final class Attribute implements Comparable<Attribute> {
Object defaultValue,
Transition configTransition,
Configurator<?, ?> configurator,
+ SplitTransitionProvider splitTransitionProvider,
Predicate<RuleClass> allowedRuleClassesForLabels,
Predicate<RuleClass> allowedRuleClassesForLabelsWarning,
FileTypeSet allowedFileTypesForLabels,
@@ -1225,6 +1302,7 @@ public final class Attribute implements Comparable<Attribute> {
this.defaultValue = defaultValue;
this.configTransition = configTransition;
this.configurator = configurator;
+ this.splitTransitionProvider = splitTransitionProvider;
this.allowedRuleClassesForLabels = allowedRuleClassesForLabels;
this.allowedRuleClassesForLabelsWarning = allowedRuleClassesForLabelsWarning;
this.allowedFileTypesForLabels = allowedFileTypesForLabels;
@@ -1329,6 +1407,25 @@ public final class Attribute implements Comparable<Attribute> {
}
/**
+ * Returns the split configuration transition for this attribute.
+ *
+ * @param rule the originating {@link Rule} which owns this attribute
+ * @throws IllegalStateException if {@link #hasSplitConfigurationTransition} is not true
+ */
+ public SplitTransition<?> getSplitTransition(Rule rule) {
+ Preconditions.checkState(hasSplitConfigurationTransition());
+ return splitTransitionProvider.apply(rule);
+ }
+
+ /**
+ * Returns true if this attribute transitions on a split transition.
+ * See {@link SplitTransition}.
+ */
+ public boolean hasSplitConfigurationTransition() {
+ return (splitTransitionProvider != null);
+ }
+
+ /**
* Returns whether the target is required to be executable for label or label
* list attributes. For other attributes it always returns {@code false}.
*/
@@ -1539,6 +1636,7 @@ public final class Attribute implements Comparable<Attribute> {
builder.validityPredicate = validityPredicate;
builder.condition = condition;
builder.configTransition = configTransition;
+ builder.splitTransitionProvider = splitTransitionProvider;
builder.propertyFlags = propertyFlags.isEmpty() ?
EnumSet.noneOf(PropertyFlag.class) : EnumSet.copyOf(propertyFlags);
builder.value = defaultValue;