Aspects can get information from their base rule.
--
MOS_MIGRATED_REVID=102126786
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
new file mode 100644
index 0000000..0cffc4c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
@@ -0,0 +1,79 @@
+// Copyright 2015 Google Inc. 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;
+
+import com.google.devtools.build.lib.packages.AspectParameters;
+
+import java.util.Objects;
+
+/**
+ * Wrapper around {@link ConfiguredAspectFactory} class and {@link AspectParameters}. Aspects are
+ * created with help of aspect factory instances and parameters are used to configure them, so we
+ * have to keep them together.
+ */
+public final class AspectWithParameters {
+ // TODO(bazel-team): class objects are not really hashable or comparable for equality other than
+ // by reference. We should identify the aspect here in a way that does not rely on comparison
+ // by reference so that keys can be serialized and deserialized properly.
+ private final Class<? extends ConfiguredAspectFactory> aspectFactory;
+ private final AspectParameters parameters;
+
+ public AspectWithParameters(
+ Class<? extends ConfiguredAspectFactory> aspect, AspectParameters parameters) {
+ this.aspectFactory = aspect;
+ this.parameters = parameters;
+ }
+
+ public AspectWithParameters(Class<? extends ConfiguredAspectFactory> aspect) {
+ this.aspectFactory = aspect;
+ this.parameters = AspectParameters.EMPTY;
+ }
+
+ /**
+ * Returns the aspectFactory required for building the aspect.
+ */
+ public Class<? extends ConfiguredAspectFactory> getAspectFactory() {
+ return aspectFactory;
+ }
+
+ /**
+ * Returns parameters for evaluation of the aspect.
+ */
+ public AspectParameters getParameters() {
+ return parameters;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof AspectWithParameters)) {
+ return false;
+ }
+ AspectWithParameters that = (AspectWithParameters) other;
+ return Objects.equals(this.aspectFactory, that.aspectFactory)
+ && Objects.equals(this.parameters, that.parameters);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(aspectFactory, parameters);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("AspectWithParameters %s(%s)", aspectFactory, parameters);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index b27c2f3..a7fff98 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -877,8 +877,8 @@
TargetAndConfiguration ctNode = new TargetAndConfiguration(target);
ListMultimap<Attribute, Dependency> depNodeNames;
try {
- depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(), null,
- getConfigurableAttributeKeys(ctNode));
+ depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(),
+ /*aspect=*/null, /*aspectParameters=*/null, getConfigurableAttributeKeys(ctNode));
} catch (EvalException e) {
throw new IllegalStateException(e);
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index f193298..9cce2f3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -31,6 +31,7 @@
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
import com.google.devtools.build.lib.packages.InputFile;
@@ -280,8 +281,10 @@
public Aspect createAspect(
AnalysisEnvironment env, RuleConfiguredTarget associatedTarget,
ConfiguredAspectFactory aspectFactory,
+ AspectParameters aspectParameters,
ListMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
- Set<ConfigMatchingProvider> configConditions, BuildConfiguration hostConfiguration) {
+ Set<ConfigMatchingProvider> configConditions,
+ BuildConfiguration hostConfiguration) {
RuleContext.Builder builder = new RuleContext.Builder(env,
associatedTarget.getTarget(),
associatedTarget.getConfiguration(),
@@ -297,7 +300,7 @@
return null;
}
- return aspectFactory.create(associatedTarget, ruleContext);
+ return aspectFactory.create(associatedTarget, ruleContext, aspectParameters);
}
/**
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 9b6ea93..f8ec20a 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
@@ -26,6 +26,7 @@
import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.AspectParameters;
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;
@@ -100,7 +101,7 @@
private final Attribute.Transition transition;
private final boolean hasStaticConfiguration;
- private final ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects;
+ private final ImmutableSet<AspectWithParameters> aspects;
/**
* Constructs a Dependency with a given configuration (suitable for static configuration
@@ -108,7 +109,7 @@
*/
public Dependency(Label label,
@Nullable BuildConfiguration configuration,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+ ImmutableSet<AspectWithParameters> aspects) {
this.label = Preconditions.checkNotNull(label);
this.configuration = configuration;
this.transition = null;
@@ -121,14 +122,14 @@
* builds).
*/
public Dependency(Label label, @Nullable BuildConfiguration configuration) {
- this(label, configuration, ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of());
+ this(label, configuration, ImmutableSet.<AspectWithParameters>of());
}
/**
* Constructs a Dependency with a given transition (suitable for dynamic configuration builds).
*/
public Dependency(Label label, Attribute.Transition transition,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+ ImmutableSet<AspectWithParameters> aspects) {
this.label = Preconditions.checkNotNull(label);
this.configuration = null;
this.transition = Preconditions.checkNotNull(transition);
@@ -165,7 +166,7 @@
return transition;
}
- public ImmutableSet<Class<? extends ConfiguredAspectFactory>> getAspects() {
+ public ImmutableSet<AspectWithParameters> getAspects() {
return aspects;
}
@@ -217,7 +218,7 @@
*/
public final ListMultimap<Attribute, Dependency> dependentNodeMap(
TargetAndConfiguration node, BuildConfiguration hostConfig, AspectDefinition aspect,
- Set<ConfigMatchingProvider> configConditions)
+ AspectParameters aspectParameters, Set<ConfigMatchingProvider> configConditions)
throws EvalException {
Target target = node.getTarget();
BuildConfiguration config = node.getConfiguration();
@@ -237,7 +238,7 @@
Rule rule = (Rule) target;
ListMultimap<Attribute, LabelAndConfiguration> labelMap =
resolveAttributes(rule, aspect, config, hostConfig, configConditions);
- visitRule(rule, aspect, labelMap, outgoingEdges);
+ visitRule(rule, aspect, aspectParameters, labelMap, outgoingEdges);
} else if (target instanceof PackageGroup) {
visitPackageGroup(node, (PackageGroup) target, outgoingEdges.get(null));
} else {
@@ -502,8 +503,8 @@
TargetAndConfiguration node, BuildConfiguration hostConfig,
Set<ConfigMatchingProvider> configConditions) {
try {
- return ImmutableSet.copyOf(
- dependentNodeMap(node, hostConfig, null, configConditions).values());
+ return ImmutableSet.copyOf(dependentNodeMap(node, hostConfig, /*aspect=*/null,
+ /*aspectParameters=*/null, configConditions).values());
} catch (EvalException e) {
throw new IllegalStateException(e);
}
@@ -516,12 +517,12 @@
* @throws IllegalArgumentException if the {@code node} does not refer to a {@link Rule} instance
*/
public final Collection<Dependency> resolveRuleLabels(
- TargetAndConfiguration node, AspectDefinition aspect, ListMultimap<Attribute,
+ TargetAndConfiguration node, ListMultimap<Attribute,
LabelAndConfiguration> labelMap) {
Preconditions.checkArgument(node.getTarget() instanceof Rule);
Rule rule = (Rule) node.getTarget();
ListMultimap<Attribute, Dependency> outgoingEdges = ArrayListMultimap.create();
- visitRule(rule, aspect, labelMap, outgoingEdges);
+ visitRule(rule, labelMap, outgoingEdges);
return outgoingEdges.values();
}
@@ -548,39 +549,59 @@
}
}
- private ImmutableSet<Class<? extends ConfiguredAspectFactory>> requiredAspects(
- AspectDefinition aspect, Attribute attribute, Target target) {
+ private ImmutableSet<AspectWithParameters> requiredAspects(AspectDefinition aspectDefinition,
+ AspectParameters aspectParameters, Attribute attribute, Target target, Rule originalRule) {
if (!(target instanceof Rule)) {
return ImmutableSet.of();
}
+ Set<AspectWithParameters> aspectCandidates =
+ extractAspectCandidates(aspectDefinition, aspectParameters, attribute, originalRule);
RuleClass ruleClass = ((Rule) target).getRuleClassObject();
+ ImmutableSet.Builder<AspectWithParameters> result = ImmutableSet.builder();
+ for (AspectWithParameters candidateClass : aspectCandidates) {
+ ConfiguredAspectFactory candidate =
+ (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass.getAspectFactory());
+ if (Sets.difference(
+ candidate.getDefinition().getRequiredProviders(),
+ ruleClass.getAdvertisedProviders()).isEmpty()) {
+ result.add(candidateClass);
+ }
+ }
+ return result.build();
+ }
+ private static Set<AspectWithParameters> extractAspectCandidates(
+ AspectDefinition aspectDefinition, AspectParameters aspectParameters,
+ Attribute attribute, Rule originalRule) {
// The order of this set will be deterministic. This is necessary because this order eventually
// influences the order in which aspects are merged into the main configured target, which in
// turn influences which aspect takes precedence if two emit the same provider (maybe this
// should be an error)
- Set<Class<? extends AspectFactory<?, ?, ?>>> aspectCandidates = new LinkedHashSet<>();
- aspectCandidates.addAll(attribute.getAspects());
- if (aspect != null) {
- aspectCandidates.addAll(aspect.getAttributeAspects().get(attribute.getName()));
+ Set<AspectWithParameters> aspectCandidates = new LinkedHashSet<>();
+ for (Map.Entry<Class<? extends AspectFactory<?, ?, ?>>, AspectParameters> aspectWithParameters :
+ attribute.getAspectsWithParameters(originalRule).entrySet()) {
+ aspectCandidates.add(new AspectWithParameters(
+ aspectWithParameters.getKey().asSubclass(ConfiguredAspectFactory.class),
+ aspectWithParameters.getValue()));
}
-
- ImmutableSet.Builder<Class<? extends ConfiguredAspectFactory>> result = ImmutableSet.builder();
- for (Class<? extends AspectFactory<?, ?, ?>> candidateClass : aspectCandidates) {
- ConfiguredAspectFactory candidate =
- (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass);
- if (Sets.difference(
- candidate.getDefinition().getRequiredProviders(),
- ruleClass.getAdvertisedProviders()).isEmpty()) {
- result.add(candidateClass.asSubclass(ConfiguredAspectFactory.class));
+ if (aspectDefinition != null) {
+ for (Class<? extends AspectFactory<?, ?, ?>> aspect :
+ aspectDefinition.getAttributeAspects().get(attribute.getName())) {
+ aspectCandidates.add(new AspectWithParameters(
+ aspect.asSubclass(ConfiguredAspectFactory.class),
+ aspectParameters));
}
}
-
- return result.build();
+ return aspectCandidates;
}
- private void visitRule(Rule rule, AspectDefinition aspect,
+ private void visitRule(Rule rule, ListMultimap<Attribute, LabelAndConfiguration> labelMap,
+ ListMultimap<Attribute, Dependency> outgoingEdges) {
+ visitRule(rule, /*aspect=*/null, /*aspectParameters=*/null, labelMap, outgoingEdges);
+ }
+
+ private void visitRule(Rule rule, AspectDefinition aspect, AspectParameters aspectParameters,
ListMultimap<Attribute, LabelAndConfiguration> labelMap,
ListMultimap<Attribute, Dependency> outgoingEdges) {
Preconditions.checkNotNull(labelMap);
@@ -622,7 +643,7 @@
config.evaluateTransition(rule, attribute, toTarget, transitionApplier);
}
for (Dependency dependency : transitionApplier.getDependencies(label,
- requiredAspects(aspect, attribute, toTarget))) {
+ requiredAspects(aspect, aspectParameters, attribute, toTarget, rule))) {
outgoingEdges.put(
entry.getKey(),
dependency);
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 29b5f4b..485786f 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
@@ -32,8 +32,8 @@
import com.google.devtools.build.lib.actions.ArtifactFactory;
import com.google.devtools.build.lib.actions.PackageRootResolver;
import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.DependencyResolver;
import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
@@ -1397,7 +1397,7 @@
* TODO(bazel-team): this is a really ugly reverse dependency: factor this away.
*/
Iterable<DependencyResolver.Dependency> getDependencies(Label label,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects);
+ ImmutableSet<AspectWithParameters> aspects);
}
/**
@@ -1471,7 +1471,7 @@
@Override
public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+ ImmutableSet<AspectWithParameters> aspects) {
return ImmutableList.of(
new DependencyResolver.Dependency(label, currentConfiguration, aspects));
}
@@ -1572,7 +1572,7 @@
@Override
public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+ ImmutableSet<AspectWithParameters> aspects) {
return ImmutableList.of(new DependencyResolver.Dependency(label, transition, aspects));
}
}
@@ -1639,7 +1639,7 @@
@Override
public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
- ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+ ImmutableSet<AspectWithParameters> aspects) {
ImmutableList.Builder<DependencyResolver.Dependency> builder = ImmutableList.builder();
for (TransitionApplier applier : appliers) {
builder.addAll(applier.getDependencies(label, aspects));