aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/Aspect.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/BuildView.java43
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTarget.java88
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java79
5 files changed, 177 insertions, 55 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/Aspect.java b/src/main/java/com/google/devtools/build/lib/analysis/Aspect.java
index fe97bfc3b4..bb6c38d9a4 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/Aspect.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/Aspect.java
@@ -22,6 +22,7 @@ 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;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.events.Location;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -88,6 +89,8 @@ public final class Aspect implements Iterable<TransitiveInfoProvider> {
private final Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider>
providers = new LinkedHashMap<>();
private final Map<String, NestedSetBuilder<Artifact>> outputGroupBuilders = new TreeMap<>();
+ private final ImmutableMap.Builder<String, Object> skylarkProviderBuilder =
+ ImmutableMap.builder();
private final String name;
public Builder(String name) {
@@ -103,6 +106,8 @@ public final class Aspect implements Iterable<TransitiveInfoProvider> {
Preconditions.checkNotNull(value);
AnalysisUtils.checkProvider(key);
Preconditions.checkState(!providers.containsKey(key));
+ Preconditions.checkArgument(!SkylarkProviders.class.equals(key),
+ "Do not provide SkylarkProviders directly");
providers.put(key, value);
return this;
}
@@ -127,6 +132,12 @@ public final class Aspect implements Iterable<TransitiveInfoProvider> {
return this;
}
+ public Builder addSkylarkTransitiveInfo(String name, Object value, Location loc) {
+ // TODO(dslomov): add {@link RuleConfiguredTargetBuilder#checkSkylarkObjectSafe}
+ skylarkProviderBuilder.put(name, value);
+ return this;
+ }
+
public Aspect build() {
if (!outputGroupBuilders.isEmpty()) {
ImmutableMap.Builder<String, NestedSet<Artifact>> outputGroups = ImmutableMap.builder();
@@ -141,6 +152,11 @@ public final class Aspect implements Iterable<TransitiveInfoProvider> {
addProvider(OutputGroupProvider.class, new OutputGroupProvider(outputGroups.build()));
}
+ ImmutableMap<String, Object> skylarkProvidersMap = skylarkProviderBuilder.build();
+ if (!skylarkProvidersMap.isEmpty()) {
+ providers.put(SkylarkProviders.class, new SkylarkProviders(skylarkProvidersMap));
+ }
+
return new Aspect(name, ImmutableMap.copyOf(providers));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index 14302ac179..e05dd596d9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -42,6 +42,7 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
@@ -75,6 +76,7 @@ import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.util.RegexFilter;
import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.WalkableGraph;
import com.google.devtools.common.options.Option;
@@ -450,18 +452,43 @@ public class BuildView {
List<AspectKey> aspectKeys = new ArrayList<>();
for (String aspect : aspects) {
- @SuppressWarnings("unchecked")
- final Class<? extends ConfiguredAspectFactory> aspectFactoryClass =
- (Class<? extends ConfiguredAspectFactory>)
- ruleClassProvider.getAspectFactoryMap().get(aspect);
- if (aspectFactoryClass != null) {
+
+ // Syntax: label%aspect
+ int delimiterPosition = aspect.indexOf('%');
+ if (delimiterPosition >= 0) {
+ PackageIdentifier bzlFile;
+ try {
+ bzlFile =
+ PackageIdentifier.create(
+ PackageIdentifier.DEFAULT_REPOSITORY,
+ new PathFragment(aspect.substring(0, delimiterPosition)));
+ } catch (LabelSyntaxException e) {
+ throw new ViewCreationFailedException("Error", e);
+ }
+
+ String skylarkFunctionName = aspect.substring(delimiterPosition + 1);
for (ConfiguredTargetKey targetSpec : targetSpecs) {
aspectKeys.add(
- AspectValue.createAspectKey(
- targetSpec.getLabel(), targetSpec.getConfiguration(), aspectFactoryClass));
+ AspectValue.createSkylarkAspectKey(
+ targetSpec.getLabel(),
+ targetSpec.getConfiguration(),
+ bzlFile,
+ skylarkFunctionName));
}
} else {
- throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
+ @SuppressWarnings("unchecked")
+ final Class<? extends ConfiguredAspectFactory> aspectFactoryClass =
+ (Class<? extends ConfiguredAspectFactory>)
+ ruleClassProvider.getAspectFactoryMap().get(aspect);
+ if (aspectFactoryClass != null) {
+ for (ConfiguredTargetKey targetSpec : targetSpecs) {
+ aspectKeys.add(
+ AspectValue.createAspectKey(
+ targetSpec.getLabel(), targetSpec.getConfiguration(), aspectFactoryClass));
+ }
+ } else {
+ throw new ViewCreationFailedException("Aspect '" + aspect + "' is unknown");
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index 6d97e86c42..a8cc9e4932 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -286,12 +286,14 @@ public final class ConfiguredTargetFactory {
* {@code aspectFactory} should call one of the error reporting methods of {@link RuleContext}.
*/
public Aspect createAspect(
- AnalysisEnvironment env, RuleConfiguredTarget associatedTarget,
+ AnalysisEnvironment env,
+ RuleConfiguredTarget associatedTarget,
ConfiguredAspectFactory aspectFactory,
AspectParameters aspectParameters,
ListMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
Set<ConfigMatchingProvider> configConditions,
- BuildConfiguration hostConfiguration) {
+ BuildConfiguration hostConfiguration)
+ throws InterruptedException {
RuleContext.Builder builder = new RuleContext.Builder(env,
associatedTarget.getTarget(),
associatedTarget.getConfiguration(),
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 9bb9365d80..d8614597a4 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
@@ -22,7 +22,6 @@ import com.google.common.collect.UnmodifiableIterator;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
import com.google.devtools.build.lib.analysis.config.RunUnder;
-import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.packages.OutputFile;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.rules.SkylarkApiProvider;
@@ -131,20 +130,14 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
providers.addAll(base.providers.keySet());
// Merge output group providers.
- OutputGroupProvider baseOutputGroupProvider = base.getProvider(OutputGroupProvider.class);
- List<OutputGroupProvider> outputGroupProviders = new ArrayList<>();
- if (baseOutputGroupProvider != null) {
- outputGroupProviders.add(baseOutputGroupProvider);
- }
+ List<OutputGroupProvider> outputGroupProviders =
+ getAllProviders(base, aspects, OutputGroupProvider.class);
+ OutputGroupProvider mergedOutputGroupProvider = OutputGroupProvider.merge(outputGroupProviders);
- for (Aspect aspect : aspects) {
- final OutputGroupProvider aspectProvider = aspect.getProvider(OutputGroupProvider.class);
- if (aspectProvider == null) {
- continue;
- }
- outputGroupProviders.add(aspectProvider);
- }
- OutputGroupProvider outputGroupProvider = OutputGroupProvider.merge(outputGroupProviders);
+ // Merge Skylark providers.
+ List<SkylarkProviders> skylarkProviders =
+ getAllProviders(base, aspects, SkylarkProviders.class);
+ SkylarkProviders mergedSkylarkProviders = SkylarkProviders.merge(skylarkProviders);
// Validate that all other providers are only provided once.
for (Aspect aspect : aspects) {
@@ -153,13 +146,17 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
if (OutputGroupProvider.class.equals(aClass)) {
continue;
}
+ if (SkylarkProviders.class.equals(aClass)) {
+ continue;
+ }
if (!providers.add(aClass)) {
throw new IllegalStateException("Provider " + aClass + " provided twice");
}
}
}
- if (baseOutputGroupProvider == outputGroupProvider) {
+ if (base.getProvider(OutputGroupProvider.class) == mergedOutputGroupProvider
+ && base.getProvider(SkylarkProviders.class) == mergedSkylarkProviders) {
this.providers = base.providers;
} else {
ImmutableMap.Builder<Class<? extends TransitiveInfoProvider>, Object> builder =
@@ -168,9 +165,17 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
if (OutputGroupProvider.class.equals(aClass)) {
continue;
}
+ if (SkylarkProviders.class.equals(aClass)) {
+ continue;
+ }
builder.put(aClass, base.providers.get(aClass));
}
- builder.put(OutputGroupProvider.class, outputGroupProvider);
+ if (mergedOutputGroupProvider != null) {
+ builder.put(OutputGroupProvider.class, mergedOutputGroupProvider);
+ }
+ if (mergedSkylarkProviders != null) {
+ builder.put(SkylarkProviders.class, skylarkProviders);
+ }
this.providers = builder.build();
}
this.mandatoryStampFiles = base.mandatoryStampFiles;
@@ -178,6 +183,26 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
this.aspects = ImmutableList.copyOf(aspects);
}
+ private static <T extends TransitiveInfoProvider> List<T> getAllProviders(
+ RuleConfiguredTarget base,
+ Iterable<Aspect> aspects,
+ Class<T> providerClass) {
+ T baseProvider = base.getProvider(providerClass);
+ List<T> providers = new ArrayList<>();
+ if (baseProvider != null) {
+ providers.add(baseProvider);
+ }
+
+ for (Aspect aspect : aspects) {
+ final T aspectProvider = aspect.getProvider(providerClass);
+ if (aspectProvider == null) {
+ continue;
+ }
+ providers.add(aspectProvider);
+ }
+ return providers;
+ }
+
/**
* The configuration conditions that trigger this rule's configurable attributes.
*/
@@ -208,7 +233,7 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
*/
@Override
public Object get(String providerKey) {
- return getProvider(SkylarkProviders.class).skylarkProviders.get(providerKey);
+ return getProvider(SkylarkProviders.class).getValue(providerKey);
}
public ImmutableList<Artifact> getMandatoryStampFiles() {
@@ -220,33 +245,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
return (Rule) super.getTarget();
}
- /**
- * A helper class for transitive infos provided by Skylark rule implementations.
- */
- @Immutable
- public static final class SkylarkProviders implements TransitiveInfoProvider {
- private final ImmutableMap<String, Object> skylarkProviders;
-
- private SkylarkProviders(ImmutableMap<String, Object> skylarkProviders) {
- Preconditions.checkNotNull(skylarkProviders);
- this.skylarkProviders = skylarkProviders;
- }
-
- /**
- * Returns the keys for the Skylark providers.
- */
- public ImmutableCollection<String> getKeys() {
- return skylarkProviders.keySet();
- }
-
- /**
- * Returns a Skylark provider; "key" must be one from {@link #getKeys()}.
- */
- public Object getValue(String key) {
- return skylarkProviders.get(key);
- }
- }
-
@Override
public UnmodifiableIterator<TransitiveInfoProvider> iterator() {
Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> allProviders =
@@ -273,6 +271,6 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
@Override
public ImmutableCollection<String> getKeys() {
return ImmutableList.<String>builder().addAll(super.getKeys())
- .addAll(getProvider(SkylarkProviders.class).skylarkProviders.keySet()).build();
+ .addAll(getProvider(SkylarkProviders.class).getKeys()).build();
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java b/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java
new file mode 100644
index 0000000000..d4746c4659
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/SkylarkProviders.java
@@ -0,0 +1,79 @@
+// Copyright 2014 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.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A helper class for transitive infos provided by Skylark rule implementations.
+ */
+@Immutable
+public final class SkylarkProviders implements TransitiveInfoProvider {
+ private final ImmutableMap<String, Object> skylarkProviders;
+
+ SkylarkProviders(ImmutableMap<String, Object> skylarkProviders) {
+ Preconditions.checkNotNull(skylarkProviders);
+ this.skylarkProviders = skylarkProviders;
+ }
+
+ /**
+ * Returns the keys for the Skylark providers.
+ */
+ public ImmutableCollection<String> getKeys() {
+ return skylarkProviders.keySet();
+ }
+
+ /**
+ * Returns a Skylark provider; "key" must be one from {@link #getKeys()}.
+ */
+ public Object getValue(String key) {
+ return skylarkProviders.get(key);
+ }
+
+ /**
+ * Merges skylark providers. The set of providers must be disjoint.
+ *
+ * @param providers providers to merge {@code this} with.
+ */
+
+ public static SkylarkProviders merge(List<SkylarkProviders> providers) {
+ if (providers.size() == 0) {
+ return null;
+ }
+ if (providers.size() == 1) {
+ return providers.get(0);
+ }
+
+ ImmutableMap.Builder<String, Object> resultBuilder = new ImmutableMap.Builder<>();
+ Set<String> seenKeys = new HashSet<>();
+ for (SkylarkProviders provider : providers) {
+ for (String key : provider.skylarkProviders.keySet()) {
+ if (!seenKeys.add(key)) {
+ // TODO(dslomov): add better diagnostics.
+ throw new IllegalStateException("Skylark provider " + key + " provided twice");
+ }
+
+ resultBuilder.put(key, provider.getValue(key));
+ }
+ }
+ return new SkylarkProviders(resultBuilder.build());
+ }
+}