aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar Lukacs Berki <lberki@google.com>2016-04-22 15:29:12 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-04-22 21:19:14 +0000
commit549bfce438156c7a26bb37449b947a60d35eab91 (patch)
tree075b4e217d49c60b1835b7686b8e44b2b65753e3 /src/main/java/com/google/devtools
parenta4e9deeeb27dffc203e1bdac2b3b98fb11bf123c (diff)
Make aspects work through bind().
bind() is assumed to be able to provide any provider. This is suboptimal, but beats the alternative of traversing the dependency graph to an arbitrary depth. The reason for the removal of the iteration ability in TransitiveInfoCollection is that now aspects can be attached to BindConfiguredTarget, too, which is not a RuleConfiguredTarget. Whereas I could have implemented the iterator, it was used only in BindConfiguredTarget anyway, so there didn't seem to be much reason to. Some work towards #952. -- MOS_MIGRATED_REVID=120549877
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/EnvironmentGroupConfiguredTarget.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/FileConfiguredTarget.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java141
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/PackageGroupConfiguredTarget.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java146
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/RuleClass.java28
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/repository/Bind.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/repository/BindRule.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java33
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalValue.java27
20 files changed, 261 insertions, 211 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
index f438c99204..645cd6d889 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredAspect.java
@@ -87,6 +87,10 @@ public final class ConfiguredAspect implements Iterable<TransitiveInfoProvider>
return providers.values().iterator();
}
+ public static ConfiguredAspect forAlias(ConfiguredAspect real) {
+ return new ConfiguredAspect(real.getName(), real.getProviders());
+ }
+
/**
* Builder for {@link ConfiguredAspect}.
*/
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 fe8bddc4a0..ef48488e4f 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
@@ -61,7 +61,6 @@ import javax.annotation.Nullable;
* <p>Includes logic to derive the right configurations depending on transition type.
*/
public abstract class DependencyResolver {
-
protected DependencyResolver() {
}
@@ -450,7 +449,7 @@ public abstract class DependencyResolver {
}
private ImmutableSet<AspectDescriptor> requiredAspects(
- Aspect aspect, Attribute attribute, Target target, Rule originalRule) {
+ Aspect aspect, Attribute attribute, final Target target, Rule originalRule) {
if (!(target instanceof Rule)) {
return ImmutableSet.of();
}
@@ -459,7 +458,7 @@ public abstract class DependencyResolver {
RuleClass ruleClass = ((Rule) target).getRuleClassObject();
ImmutableSet.Builder<AspectDescriptor> result = ImmutableSet.builder();
for (Aspect aspectCandidate : aspectCandidates) {
- if (Sets.difference(
+ if (ruleClass.canHaveAnyProvider() || Sets.difference(
aspectCandidate.getDefinition().getRequiredProviders(),
ruleClass.getAdvertisedProviders())
.isEmpty()) {
@@ -499,8 +498,9 @@ public abstract class DependencyResolver {
return aspectCandidates;
}
- private void visitRule(Rule rule, ListMultimap<Attribute, LabelAndConfiguration> labelMap,
- NestedSetBuilder<Label> rootCauses, ListMultimap<Attribute, Dependency> outgoingEdges) {
+ private void visitRule(Rule rule,
+ ListMultimap<Attribute, LabelAndConfiguration> labelMap, NestedSetBuilder<Label> rootCauses,
+ ListMultimap<Attribute, Dependency> outgoingEdges) {
visitRule(rule, /*aspect=*/ null, labelMap, rootCauses, outgoingEdges);
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/EnvironmentGroupConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/EnvironmentGroupConfiguredTarget.java
index dd1c29fb21..3465a1ddda 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/EnvironmentGroupConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/EnvironmentGroupConfiguredTarget.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.analysis;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.packages.EnvironmentGroup;
import com.google.devtools.build.lib.util.Preconditions;
@@ -38,9 +37,4 @@ public final class EnvironmentGroupConfiguredTarget extends AbstractConfiguredTa
// No providers.
return null;
}
-
- @Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- throw new UnsupportedOperationException();
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/FileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/FileConfiguredTarget.java
index 86b837fbed..42178bf531 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/FileConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/FileConfiguredTarget.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.analysis;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -83,9 +82,4 @@ public abstract class FileConfiguredTarget extends AbstractConfiguredTarget
public Object get(String providerKey) {
return null;
}
-
- @Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- return providers.values().iterator();
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java
new file mode 100644
index 0000000000..6e01d8ec1f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java
@@ -0,0 +1,141 @@
+// Copyright 2016 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;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A single dependency with its configured target and aspects merged together.
+ *
+ * <p>This is an ephemeral object created only for the analysis of a single configured target.
+ * After that configured target is analyzed, this is thrown away.
+ */
+public class MergedConfiguredTarget extends AbstractConfiguredTarget {
+ private final ConfiguredTarget base;
+ private final ImmutableMap<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider>
+ providers;
+
+ private MergedConfiguredTarget(ConfiguredTarget base,
+ ImmutableMap<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> providers) {
+ super(base.getTarget(), base.getConfiguration());
+ this.base = base;
+ this.providers = providers;
+ }
+
+ /**
+ * Returns a value provided by this target. Only meant to use from Skylark.
+ */
+ @Override
+ public Object get(String providerKey) {
+ return getProvider(SkylarkProviders.class).getValue(providerKey);
+ }
+
+ @Override
+ public <P extends TransitiveInfoProvider> P getProvider(Class<P> providerClass) {
+ AnalysisUtils.checkProvider(providerClass);
+
+ Object provider = providers.get(providerClass);
+ if (provider == null) {
+ provider = base.getProvider(providerClass);
+ }
+
+ return providerClass.cast(provider);
+ }
+
+ /**
+ * Creates an instance based on a configured target and a set of aspects.
+ */
+ public static ConfiguredTarget of(ConfiguredTarget base,
+ Iterable<ConfiguredAspect> aspects) {
+ if (Iterables.isEmpty(aspects)) {
+ // If there are no aspects, don't bother with creating a proxy object
+ return base;
+ }
+
+ Set<Class<? extends TransitiveInfoProvider>> providers = new HashSet<>();
+
+ ImmutableSet<Class<? extends TransitiveInfoProvider>> baseProviders =
+ ImmutableSet.copyOf(providers);
+
+ // Merge output group providers.
+ OutputGroupProvider mergedOutputGroupProvider =
+ OutputGroupProvider.merge(getAllProviders(base, aspects, OutputGroupProvider.class));
+
+ // Merge Skylark providers.
+ SkylarkProviders mergedSkylarkProviders =
+ SkylarkProviders.merge(getAllProviders(base, aspects, SkylarkProviders.class));
+
+ // Merge extra-actions provider.
+ ExtraActionArtifactsProvider mergedExtraActionProviders = ExtraActionArtifactsProvider.merge(
+ getAllProviders(base, aspects, ExtraActionArtifactsProvider.class));
+
+ Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> aspectProviders =
+ new LinkedHashMap<>();
+ if (mergedOutputGroupProvider != null) {
+ aspectProviders.put(OutputGroupProvider.class, mergedOutputGroupProvider);
+ }
+ if (mergedSkylarkProviders != null) {
+ aspectProviders.put(SkylarkProviders.class, mergedSkylarkProviders);
+ }
+ if (mergedExtraActionProviders != null) {
+ aspectProviders.put(ExtraActionArtifactsProvider.class, mergedExtraActionProviders);
+ }
+
+ for (ConfiguredAspect aspect : aspects) {
+ for (Map.Entry<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> entry :
+ aspect.getProviders().entrySet()) {
+ if (OutputGroupProvider.class.equals(entry.getKey())
+ || SkylarkProviders.class.equals(entry.getKey())
+ || ExtraActionArtifactsProvider.class.equals(entry.getKey())) {
+ continue;
+ }
+
+ if (base.getProvider(entry.getKey()) != null
+ || aspectProviders.containsKey(entry.getKey())) {
+ throw new IllegalStateException("Provider " + entry.getKey() + " provided twice");
+ }
+
+ aspectProviders.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return new MergedConfiguredTarget(base, ImmutableMap.copyOf(aspectProviders));
+ }
+
+ private static <T extends TransitiveInfoProvider> List<T> getAllProviders(
+ ConfiguredTarget base, Iterable<ConfiguredAspect> aspects, Class<T> providerClass) {
+ T baseProvider = base.getProvider(providerClass);
+ List<T> providers = new ArrayList<>();
+ if (baseProvider != null) {
+ providers.add(baseProvider);
+ }
+
+ for (ConfiguredAspect configuredAspect : aspects) {
+ final T aspectProvider = configuredAspect.getProvider(providerClass);
+ if (aspectProvider == null) {
+ continue;
+ }
+ providers.add(aspectProvider);
+ }
+ return providers;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/PackageGroupConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/PackageGroupConfiguredTarget.java
index c148ecd0bf..549932daa0 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/PackageGroupConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/PackageGroupConfiguredTarget.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.analysis;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -70,9 +69,4 @@ public final class PackageGroupConfiguredTarget extends AbstractConfiguredTarget
// No providers.
return null;
}
-
- @Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- throw new UnsupportedOperationException();
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java
index 9773cc1062..211097f45d 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java
@@ -16,8 +16,6 @@ package com.google.devtools.build.lib.analysis;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.packages.OutputFile;
@@ -25,10 +23,7 @@ import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.SkylarkApiProvider;
import com.google.devtools.build.lib.util.Preconditions;
-import java.util.ArrayList;
-import java.util.HashSet;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -51,7 +46,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
private final ImmutableMap<Class<? extends TransitiveInfoProvider>, Object> providers;
private final Set<ConfigMatchingProvider> configConditions;
- private final ImmutableList<ConfiguredAspect> configuredAspects;
RuleConfiguredTarget(RuleContext ruleContext,
ImmutableMap<String, Object> skylarkProviders,
@@ -76,7 +70,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
this.providers = ImmutableMap.copyOf(providerBuilder);
this.configConditions = ruleContext.getConfigConditions();
- this.configuredAspects = ImmutableList.of();
// If this rule is the run_under target, then check that we have an executable; note that
// run_under is only set in the target configuration, and the target must also be analyzed for
@@ -98,117 +91,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
}
/**
- * Merge a configured target with its associated aspects.
- *
- * <p>If aspects are present, the configured target must be created from a rule (instead of e.g.
- * an input or an output file).
- */
- public static ConfiguredTarget mergeAspects(
- ConfiguredTarget base, Iterable<ConfiguredAspect> aspects) {
- if (Iterables.isEmpty(aspects)) {
- // If there are no aspects, don't bother with creating a proxy object
- return base;
- } else {
- // Aspects can only be attached to rules for now. This invariant is upheld by
- // DependencyResolver#requiredAspects()
- return new RuleConfiguredTarget((RuleConfiguredTarget) base, aspects);
- }
- }
-
- /**
- * Creates an instance based on a configured target and a set of aspects.
- */
- private RuleConfiguredTarget(RuleConfiguredTarget base, Iterable<ConfiguredAspect> aspects) {
- super(base.getTarget(), base.getConfiguration());
-
- Set<Class<? extends TransitiveInfoProvider>> providers = new HashSet<>();
-
- providers.addAll(base.providers.keySet());
-
- // Merge output group providers.
- OutputGroupProvider mergedOutputGroupProvider =
- OutputGroupProvider.merge(getAllProviders(base, aspects, OutputGroupProvider.class));
-
- // Merge Skylark providers.
- SkylarkProviders mergedSkylarkProviders =
- SkylarkProviders.merge(getAllProviders(base, aspects, SkylarkProviders.class));
-
- // Merge extra-actions provider.
- ExtraActionArtifactsProvider mergedExtraActionProviders = ExtraActionArtifactsProvider.merge(
- getAllProviders(base, aspects, ExtraActionArtifactsProvider.class));
-
- // Validate that all other providers are only provided once.
- for (ConfiguredAspect configuredAspect : aspects) {
- for (TransitiveInfoProvider aspectProvider : configuredAspect) {
- Class<? extends TransitiveInfoProvider> aClass = aspectProvider.getClass();
- if (OutputGroupProvider.class.equals(aClass)) {
- continue;
- }
- if (SkylarkProviders.class.equals(aClass)) {
- continue;
- }
- if (ExtraActionArtifactsProvider.class.equals(aClass)) {
- continue;
- }
- if (!providers.add(aClass)) {
- throw new IllegalStateException("Provider " + aClass + " provided twice");
- }
- }
- }
-
- if (base.getProvider(OutputGroupProvider.class) == mergedOutputGroupProvider
- && base.getProvider(SkylarkProviders.class) == mergedSkylarkProviders
- && base.getProvider(ExtraActionArtifactsProvider.class) == mergedExtraActionProviders) {
- this.providers = base.providers;
- } else {
- ImmutableMap.Builder<Class<? extends TransitiveInfoProvider>, Object> builder =
- new ImmutableMap.Builder<>();
- for (Class<? extends TransitiveInfoProvider> aClass : base.providers.keySet()) {
- if (OutputGroupProvider.class.equals(aClass)) {
- continue;
- }
- if (SkylarkProviders.class.equals(aClass)) {
- continue;
- }
- if (ExtraActionArtifactsProvider.class.equals(aClass)) {
- continue;
- }
- builder.put(aClass, base.providers.get(aClass));
- }
- if (mergedOutputGroupProvider != null) {
- builder.put(OutputGroupProvider.class, mergedOutputGroupProvider);
- }
- if (mergedSkylarkProviders != null) {
- builder.put(SkylarkProviders.class, mergedSkylarkProviders);
- }
- if (mergedExtraActionProviders != null) {
- builder.put(ExtraActionArtifactsProvider.class, mergedExtraActionProviders);
- }
- this.providers = builder.build();
- }
- this.configConditions = base.configConditions;
- this.configuredAspects = ImmutableList.copyOf(aspects);
- }
-
- private static <T extends TransitiveInfoProvider> List<T> getAllProviders(
- RuleConfiguredTarget base, Iterable<ConfiguredAspect> aspects, Class<T> providerClass) {
- T baseProvider = base.getProvider(providerClass);
- List<T> providers = new ArrayList<>();
- if (baseProvider != null) {
- providers.add(baseProvider);
- }
-
- for (ConfiguredAspect configuredAspect : aspects) {
- final T aspectProvider = configuredAspect.getProvider(providerClass);
- if (aspectProvider == null) {
- continue;
- }
- providers.add(aspectProvider);
- }
- return providers;
- }
-
- /**
* The configuration conditions that trigger this rule's configurable attributes.
*/
Set<ConfigMatchingProvider> getConfigConditions() {
@@ -222,15 +104,10 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
// class?
Object provider = providers.get(providerClass);
if (provider == null) {
- for (ConfiguredAspect configuredAspect : configuredAspects) {
- provider = configuredAspect.getProviders().get(providerClass);
- if (provider != null) {
- break;
- }
- }
+ return null;
+ } else {
+ return providerClass.cast(provider);
}
-
- return providerClass.cast(provider);
}
/**
@@ -247,23 +124,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
}
@Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> allProviders =
- new LinkedHashMap<>();
- for (int i = configuredAspects.size() - 1; i >= 0; i--) {
- for (TransitiveInfoProvider tip : configuredAspects.get(i)) {
- allProviders.put(tip.getClass(), tip);
- }
- }
-
- for (Map.Entry<Class<? extends TransitiveInfoProvider>, Object> entry : providers.entrySet()) {
- allProviders.put(entry.getKey(), entry.getKey().cast(entry.getValue()));
- }
-
- return ImmutableList.copyOf(allProviders.values()).iterator();
- }
-
- @Override
public String errorMessage(String name) {
return String.format("target (rule class of '%s') doesn't have provider '%s'.",
getTarget().getRuleClass(), name);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
index 2264d8ff17..42b829785f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/TransitiveInfoCollection.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.analysis;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
@@ -95,7 +94,7 @@ import javax.annotation.Nullable;
+ "These extra providers are defined in the <code>struct</code> returned by the rule "
+ "implementation function.</li>"
+ "</ul>")
-public interface TransitiveInfoCollection extends Iterable<TransitiveInfoProvider> {
+public interface TransitiveInfoCollection {
/**
* Returns the transitive information provider requested, or null if the provider is not found.
@@ -121,10 +120,4 @@ public interface TransitiveInfoCollection extends Iterable<TransitiveInfoProvide
* The transitive information has to have been added using the Skylark framework.
*/
@Nullable Object get(String providerKey);
-
- /**
- * Returns an unmodifiable iterator over the transitive info providers in the collections.
- */
- @Override
- UnmodifiableIterator<TransitiveInfoProvider> iterator();
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
index 9d2af18fb9..be1bd0bb6f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/AspectDefinition.java
@@ -147,16 +147,17 @@ public final class AspectDefinition {
}
RuleClass ruleClass = ((Rule) to).getRuleClassObject();
ImmutableSet<Class<?>> providers = ruleClass.getAdvertisedProviders();
- return visitAspectsIfRequired((Rule) from, attribute, toStringSet(providers), dependencyFilter);
+ return visitAspectsIfRequired((Rule) from, attribute, ruleClass.canHaveAnyProvider(),
+ toStringSet(providers), dependencyFilter);
}
/**
* Returns the attribute -&gt; set of labels that are provided by aspects of attribute.
*/
public static ImmutableMultimap<Attribute, Label> visitAspectsIfRequired(
- Rule from, Attribute attribute, Set<String> advertisedProviders,
+ Rule from, Attribute attribute, boolean canHaveAnyProvider, Set<String> advertisedProviders,
DependencyFilter dependencyFilter) {
- if (advertisedProviders.isEmpty()) {
+ if (advertisedProviders.isEmpty() && !canHaveAnyProvider) {
return ImmutableMultimap.of();
}
@@ -164,7 +165,7 @@ public final class AspectDefinition {
for (Aspect candidateClass : attribute.getAspects(from)) {
// Check if target satisfies condition for this aspect (has to provide all required
// TransitiveInfoProviders)
- if (!advertisedProviders.containsAll(
+ if (!canHaveAnyProvider && !advertisedProviders.containsAll(
candidateClass.getDefinition().getRequiredProviderNames())) {
continue;
}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 18e69a270d..7fd42dcca3 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -477,6 +477,7 @@ public final class RuleClass {
PredicatesWithMessage.<Rule>alwaysTrue();
private Predicate<String> preferredDependencyPredicate = Predicates.alwaysFalse();
private List<Class<?>> advertisedProviders = new ArrayList<>();
+ private boolean canHaveAnyProvider = false;
private BaseFunction configuredTargetFunction = null;
private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
NO_EXTERNAL_BINDINGS;
@@ -571,7 +572,7 @@ public final class RuleClass {
return new RuleClass(name, skylark, skylarkExecutable, documented, publicByDefault,
binaryOutput, workspaceOnly, outputsDefaultExecutable, implicitOutputsFunction,
configurator, configuredTargetFactory, validityPredicate, preferredDependencyPredicate,
- ImmutableSet.copyOf(advertisedProviders), configuredTargetFunction,
+ ImmutableSet.copyOf(advertisedProviders), canHaveAnyProvider, configuredTargetFunction,
externalBindingsFunction, ruleDefinitionEnvironment, configurationFragmentPolicy.build(),
supportsConstraintChecking, attributes.values().toArray(new Attribute[0]));
}
@@ -726,10 +727,21 @@ public final class RuleClass {
* not be evaluated for the rule.
*/
public Builder advertiseProvider(Class<?>... providers) {
+ Preconditions.checkState(!canHaveAnyProvider);
Collections.addAll(advertisedProviders, providers);
return this;
}
+ /**
+ * Set if the rule can have any provider. This is true for "alias" rules like
+ * <code>bind</code> .
+ */
+ public Builder canHaveAnyProvider() {
+ Preconditions.checkState(advertisedProviders.isEmpty());
+ canHaveAnyProvider = true;
+ return this;
+ }
+
private void addAttribute(Attribute attribute) {
Preconditions.checkState(!attributes.containsKey(attribute.getName()),
"An attribute with the name '%s' already exists.", attribute.getName());
@@ -967,6 +979,8 @@ public final class RuleClass {
*/
private final ImmutableSet<Class<?>> advertisedProviders;
+ private final boolean canHaveAnyProvider;
+
/**
* The Skylark rule implementation of this RuleClass. Null for non Skylark executable RuleClasses.
*/
@@ -1012,6 +1026,7 @@ public final class RuleClass {
PredicateWithMessage<Rule> validityPredicate,
Predicate<String> preferredDependencyPredicate,
ImmutableSet<Class<?>> advertisedProviders,
+ boolean canHaveAnyProvider,
@Nullable BaseFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
@Nullable Environment ruleDefinitionEnvironment,
@@ -1033,6 +1048,7 @@ public final class RuleClass {
validityPredicate,
preferredDependencyPredicate,
advertisedProviders,
+ canHaveAnyProvider,
configuredTargetFunction,
externalBindingsFunction,
ruleDefinitionEnvironment,
@@ -1075,6 +1091,7 @@ public final class RuleClass {
ConfiguredTargetFactory<?, ?> configuredTargetFactory,
PredicateWithMessage<Rule> validityPredicate, Predicate<String> preferredDependencyPredicate,
ImmutableSet<Class<?>> advertisedProviders,
+ boolean canHaveAnyProvider,
@Nullable BaseFunction configuredTargetFunction,
Function<? super Rule, Map<String, Label>> externalBindingsFunction,
@Nullable Environment ruleDefinitionEnvironment,
@@ -1094,6 +1111,7 @@ public final class RuleClass {
this.validityPredicate = validityPredicate;
this.preferredDependencyPredicate = preferredDependencyPredicate;
this.advertisedProviders = advertisedProviders;
+ this.canHaveAnyProvider = canHaveAnyProvider;
this.configuredTargetFunction = configuredTargetFunction;
this.externalBindingsFunction = externalBindingsFunction;
this.ruleDefinitionEnvironment = ruleDefinitionEnvironment;
@@ -1269,6 +1287,14 @@ public final class RuleClass {
}
/**
+ * Returns true if this rule, when analyzed, can provide any provider. Used for "alias" rules,
+ * e.g. <code>bind()</code>.
+ */
+ public boolean canHaveAnyProvider() {
+ return canHaveAnyProvider;
+ }
+
+ /**
* For --compile_one_dependency: if multiple rules consume the specified target,
* should we choose this one over the "unpreferred" options?
*/
diff --git a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
index 470a11e2df..8a90c10ff5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/TargetUtils.java
@@ -256,4 +256,17 @@ public final class TargetUtils {
return e.getMessage();
}
}
+
+ public static Label getAliasTarget(Target target) {
+ if (!(target instanceof Rule)) {
+ return null;
+ }
+
+ Rule rule = (Rule) target;
+ if (!rule.getRuleClass().equals("bind")) {
+ return null;
+ }
+
+ return AggregatingAttributeMapper.of(rule).get("actual", BuildType.LABEL);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java
index e66847e422..ff0c743a52 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibraryHelper.java
@@ -19,7 +19,6 @@ import static com.google.devtools.build.lib.analysis.config.BuildConfiguration.S
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
@@ -183,11 +182,6 @@ public final class JavaLibraryHelper {
public Object get(String providerKey) {
throw new UnsupportedOperationException();
}
-
- @Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- throw new UnsupportedOperationException();
- }
};
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/Bind.java b/src/main/java/com/google/devtools/build/lib/rules/repository/Bind.java
index db927bc746..6ea3edeab9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/Bind.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/Bind.java
@@ -16,7 +16,6 @@ package com.google.devtools.build.lib.rules.repository;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.FileProvider;
@@ -72,13 +71,6 @@ public class Bind implements RuleConfiguredTargetFactory {
}
@Override
- public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
- return configuredTarget == null
- ? ImmutableList.<TransitiveInfoProvider>of().iterator()
- : configuredTarget.iterator();
- }
-
- @Override
public Target getTarget() {
return configuredTarget == null ? null : configuredTarget.getTarget();
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/repository/BindRule.java b/src/main/java/com/google/devtools/build/lib/rules/repository/BindRule.java
index 9457d3b351..da7ffb36d3 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/repository/BindRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/repository/BindRule.java
@@ -45,6 +45,7 @@ public final class BindRule implements RuleDefinition {
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
.add(attr("actual", LABEL).allowedFileTypes(FileTypeSet.ANY_FILE))
.setWorkspaceOnly()
+ .canHaveAnyProvider()
.build();
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
index d3254459bf..56878b153b 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectFunction.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.skyframe;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
+import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
@@ -42,6 +43,7 @@ import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.packages.SkylarkAspectClass;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.SkylarkRuleClassFunctions.SkylarkAspect;
import com.google.devtools.build.lib.skyframe.AspectValue.AspectKey;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
@@ -167,6 +169,11 @@ public final class AspectFunction implements SkyFunction {
throw new AspectFunctionException(e);
}
+ Label aliasLabel = TargetUtils.getAliasTarget(target);
+ if (aliasLabel != null) {
+ return createAliasAspect(env, target, aliasLabel, aspect, key);
+ }
+
if (!(target instanceof Rule)) {
throw new AspectFunctionException(new AspectCreationException(
"aspects must be attached to rules"));
@@ -259,6 +266,32 @@ public final class AspectFunction implements SkyFunction {
}
}
+ private SkyValue createAliasAspect(Environment env, Target originalTarget, Label aliasLabel,
+ Aspect aspect, AspectKey originalKey) {
+ SkyKey depKey = AspectValue.key(aliasLabel,
+ originalKey.getAspectConfiguration(),
+ originalKey.getBaseConfiguration(),
+ originalKey.getAspectClass(),
+ originalKey.getParameters());
+ AspectValue real = (AspectValue) env.getValue(depKey);
+ if (env.valuesMissing()) {
+ return null;
+ }
+
+ NestedSet<Package> transitivePackages = NestedSetBuilder.<Package>stableOrder()
+ .addTransitive(real.getTransitivePackages())
+ .add(originalTarget.getPackage())
+ .build();
+ return new AspectValue(
+ originalKey,
+ aspect,
+ originalTarget.getLabel(),
+ originalTarget.getLocation(),
+ ConfiguredAspect.forAlias(real.getConfiguredAspect()),
+ ImmutableList.<Action>of(),
+ transitivePackages);
+ }
+
@Nullable
private AspectValue createAspect(
Environment env,
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
index 4701750eb6..0a5caf065e 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConfiguredTargetFunction.java
@@ -33,7 +33,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.Dependency;
import com.google.devtools.build.lib.analysis.LabelAndConfiguration;
-import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
+import com.google.devtools.build.lib.analysis.MergedConfiguredTarget;
import com.google.devtools.build.lib.analysis.TargetAndConfiguration;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
@@ -579,7 +579,7 @@ final class ConfiguredTargetFunction implements SkyFunction {
SkyKey depKey = TO_KEYS.apply(dep);
ConfiguredTarget depConfiguredTarget = depConfiguredTargetMap.get(depKey);
result.put(entry.getKey(),
- RuleConfiguredTarget.mergeAspects(depConfiguredTarget, depAspectMap.get(depKey)));
+ MergedConfiguredTarget.of(depConfiguredTarget, depAspectMap.get(depKey)));
}
return result;
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 60904c1e18..ca8dfadd2d 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
@@ -54,7 +54,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.Dependency;
-import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
+import com.google.devtools.build.lib.analysis.MergedConfiguredTarget;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction.Factory;
@@ -1197,7 +1197,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory {
configuredAspects.add(((AspectValue) result.get(aspectKey)).getConfiguredAspect());
}
- cts.put(key, RuleConfiguredTarget.mergeAspects(configuredTarget, configuredAspects));
+ cts.put(key, MergedConfiguredTarget.of(configuredTarget, configuredAspects));
}
return cts.build();
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
index 4035bfaf6e..8a0c4f1019 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
@@ -216,7 +216,7 @@ public class TransitiveTargetFunction
protected Collection<Label> getAspectLabels(Rule fromRule, Attribute attr, Label toLabel,
ValueOrException2<NoSuchPackageException, NoSuchTargetException> toVal,
- Environment env) {
+ final Environment env) {
SkyKey packageKey = PackageValue.key(toLabel.getPackageIdentifier());
try {
PackageValue pkgValue =
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
index 338d9c0e46..1852793e70 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalFunction.java
@@ -32,7 +32,6 @@ import com.google.devtools.build.skyframe.ValueOrException2;
import java.util.Collection;
import java.util.Map.Entry;
-import java.util.Set;
import javax.annotation.Nullable;
@@ -96,8 +95,8 @@ public class TransitiveTraversalFunction
}
// Retrieve the providers of the dep from the TransitiveTraversalValue, so we can avoid
// issuing a dep on its defining Package.
- Set<String> providers = traversalVal.getProviders();
- return AspectDefinition.visitAspectsIfRequired(fromRule, attr, providers,
+ return AspectDefinition.visitAspectsIfRequired(fromRule, attr,
+ traversalVal.canHaveAnyProvider(), traversalVal.getProviders(),
DependencyFilter.ALL_DEPS).values();
} catch (NoSuchThingException e) {
// Do nothing. This error was handled when we computed the corresponding
@@ -107,8 +106,8 @@ public class TransitiveTraversalFunction
}
@Override
- SkyValue computeSkyValue(
- TargetAndErrorIfAny targetAndErrorIfAny, FirstErrorMessageAccumulator accumulator) {
+ SkyValue computeSkyValue(TargetAndErrorIfAny targetAndErrorIfAny,
+ FirstErrorMessageAccumulator accumulator) {
boolean targetLoadedSuccessfully = targetAndErrorIfAny.getErrorLoadingTarget() == null;
String firstErrorMessage = accumulator.getFirstErrorMessage();
return targetLoadedSuccessfully
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalValue.java
index 2070ff2b66..35fdc9ab15 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTraversalValue.java
@@ -39,19 +39,20 @@ import javax.annotation.Nullable;
@Immutable
@ThreadSafe
public class TransitiveTraversalValue implements SkyValue {
-
+ private final boolean canHaveAnyProvider;
@Nullable private final ImmutableSet<String> providers;
@Nullable private final String firstErrorMessage;
- private TransitiveTraversalValue(
+ private TransitiveTraversalValue(boolean canHaveAnyProvider,
@Nullable Iterable<String> providers, @Nullable String firstErrorMessage) {
+ this.canHaveAnyProvider = canHaveAnyProvider;
this.providers = (providers == null) ? null : canonicalSet(providers);
this.firstErrorMessage =
(firstErrorMessage == null) ? null : StringCanonicalizer.intern(firstErrorMessage);
}
public static TransitiveTraversalValue unsuccessfulTransitiveTraversal(String firstErrorMessage) {
- return new TransitiveTraversalValue(null, Preconditions.checkNotNull(firstErrorMessage));
+ return new TransitiveTraversalValue(false, null, Preconditions.checkNotNull(firstErrorMessage));
}
public static TransitiveTraversalValue forTarget(
@@ -59,14 +60,16 @@ public class TransitiveTraversalValue implements SkyValue {
if (target instanceof Rule) {
Rule rule = (Rule) target;
return new TransitiveTraversalValue(
- toStringSet(rule.getRuleClassObject().getAdvertisedProviders()), firstErrorMessage);
+ rule.getRuleClassObject().canHaveAnyProvider(),
+ toStringSet(rule.getRuleClassObject().getAdvertisedProviders()),
+ firstErrorMessage);
}
- return new TransitiveTraversalValue(ImmutableList.<String>of(), firstErrorMessage);
+ return new TransitiveTraversalValue(false, ImmutableList.<String>of(), firstErrorMessage);
}
public static TransitiveTraversalValue withProviders(
Collection<String> providers, @Nullable String firstErrorMessage) {
- return new TransitiveTraversalValue(ImmutableSet.copyOf(providers), firstErrorMessage);
+ return new TransitiveTraversalValue(false, ImmutableSet.copyOf(providers), firstErrorMessage);
}
private static ImmutableSet<String> canonicalSet(Iterable<String> strIterable) {
@@ -88,6 +91,13 @@ public class TransitiveTraversalValue implements SkyValue {
}
/**
+ * Returns if the associated target can have any provider. True for "alias" rules.
+ */
+ public boolean canHaveAnyProvider() {
+ return canHaveAnyProvider;
+ }
+
+ /**
* Returns the set of provider names from the target, if the target is a {@link Rule}. If there
* were errors loading the target, returns {@code null}.
*/
@@ -115,12 +125,13 @@ public class TransitiveTraversalValue implements SkyValue {
}
TransitiveTraversalValue that = (TransitiveTraversalValue) o;
return Objects.equals(this.firstErrorMessage, that.firstErrorMessage)
- && Objects.equals(this.providers, that.providers);
+ && Objects.equals(this.providers, that.providers)
+ && Objects.equals(this.canHaveAnyProvider, canHaveAnyProvider);
}
@Override
public int hashCode() {
- return 31 * Objects.hashCode(firstErrorMessage) + Objects.hashCode(providers);
+ return Objects.hash(firstErrorMessage, providers, canHaveAnyProvider);
}
@ThreadSafe