diff options
Diffstat (limited to 'src/main/java/com/google')
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 -> 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 |