aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google')
-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