Implement default provider
Default providers can now be used not only to return standard providers values
from a rule implementation function, but also to access these values provided
by other rules.
PiperOrigin-RevId: 152797193
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AbstractConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/AbstractConfiguredTarget.java
index d32b279..f5313b8 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AbstractConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AbstractConfiguredTarget.java
@@ -16,7 +16,6 @@
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -27,10 +26,10 @@
import com.google.devtools.build.lib.packages.PackageSpecification;
import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier;
import com.google.devtools.build.lib.packages.Target;
+import com.google.devtools.build.lib.rules.SkylarkRuleContext;
import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
-import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import javax.annotation.Nullable;
/**
@@ -108,19 +107,17 @@
@Override
public Object getValue(String name) {
+ // Standard fields should be proxied to their default provider object
+ DefaultProvider defaultProvider =
+ (DefaultProvider) get(SkylarkRuleContext.getDefaultProvider().getKey());
switch (name) {
+ case FILES_FIELD:
+ case DEFAULT_RUNFILES_FIELD:
+ case DATA_RUNFILES_FIELD:
+ case FilesToRunProvider.SKYLARK_NAME:
+ return defaultProvider.getValue(name);
case LABEL_FIELD:
return getLabel();
- case FILES_FIELD:
- // A shortcut for files to build in Skylark. FileConfiguredTarget and RuleConfiguredTarget
- // always has FileProvider and Error- and PackageGroupConfiguredTarget-s shouldn't be
- // accessible in Skylark.
- return SkylarkNestedSet.of(
- Artifact.class, getProvider(FileProvider.class).getFilesToBuild());
- case DEFAULT_RUNFILES_FIELD:
- return RunfilesProvider.DEFAULT_RUNFILES.apply(this);
- case DATA_RUNFILES_FIELD:
- return RunfilesProvider.DATA_RUNFILES.apply(this);
default:
return get(name);
}
@@ -173,6 +170,10 @@
@Override
public ImmutableCollection<String> getKeys() {
return ImmutableList.of(
- DATA_RUNFILES_FIELD, DEFAULT_RUNFILES_FIELD, LABEL_FIELD, FILES_FIELD);
+ DATA_RUNFILES_FIELD,
+ DEFAULT_RUNFILES_FIELD,
+ LABEL_FIELD,
+ FILES_FIELD,
+ FilesToRunProvider.SKYLARK_NAME);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DefaultProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/DefaultProvider.java
new file mode 100644
index 0000000..c0c2a31
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DefaultProvider.java
@@ -0,0 +1,58 @@
+// Copyright 2017 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.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+import com.google.devtools.build.lib.packages.ClassObjectConstructor;
+import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.rules.SkylarkRuleContext;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import java.util.Map;
+
+/** DefaultProvider is provided by all targets implicitly and contains all standard fields. */
+@Immutable
+public final class DefaultProvider extends SkylarkClassObject {
+
+ // Accessors for Skylark
+ private static final String DATA_RUNFILES_FIELD = "data_runfiles";
+ private static final String DEFAULT_RUNFILES_FIELD = "default_runfiles";
+ private static final String FILES_FIELD = "files";
+
+ private DefaultProvider(ClassObjectConstructor constructor, Map<String, Object> values) {
+ super(constructor, values);
+ }
+
+ public static DefaultProvider build(
+ RunfilesProvider runfilesProvider,
+ FileProvider fileProvider,
+ FilesToRunProvider filesToRunProvider) {
+ ImmutableMap.Builder<String, Object> attrBuilder = new ImmutableMap.Builder<>();
+ if (runfilesProvider != null) {
+ attrBuilder.put(DATA_RUNFILES_FIELD, runfilesProvider.getDataRunfiles());
+ attrBuilder.put(DEFAULT_RUNFILES_FIELD, runfilesProvider.getDefaultRunfiles());
+ } else {
+ attrBuilder.put(DATA_RUNFILES_FIELD, Runfiles.EMPTY);
+ attrBuilder.put(DEFAULT_RUNFILES_FIELD, Runfiles.EMPTY);
+ }
+
+ attrBuilder.put(
+ FILES_FIELD, SkylarkNestedSet.of(Artifact.class, fileProvider.getFilesToBuild()));
+ attrBuilder.put(FilesToRunProvider.SKYLARK_NAME, filesToRunProvider);
+
+ ClassObjectConstructor constructor = SkylarkRuleContext.getDefaultProvider();
+ return new DefaultProvider(constructor, attrBuilder.build());
+ }
+}
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 0bc9b53..0fe798b 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
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.analysis;
+import com.google.common.collect.ImmutableMap;
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;
@@ -21,6 +22,7 @@
import com.google.devtools.build.lib.packages.ClassObjectConstructor;
import com.google.devtools.build.lib.packages.FileTarget;
import com.google.devtools.build.lib.packages.SkylarkClassObject;
+import com.google.devtools.build.lib.rules.SkylarkRuleContext;
import com.google.devtools.build.lib.rules.fileset.FilesetProvider;
import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
import com.google.devtools.build.lib.util.FileType;
@@ -40,12 +42,22 @@
super(targetContext);
NestedSet<Artifact> filesToBuild = NestedSetBuilder.create(Order.STABLE_ORDER, artifact);
this.artifact = artifact;
+ FileProvider fileProvider = new FileProvider(filesToBuild);
+ FilesToRunProvider filesToRunProvider =
+ FilesToRunProvider.fromSingleExecutableArtifact(artifact);
+ SkylarkClassObject defaultProvider =
+ DefaultProvider.build(null, fileProvider, filesToRunProvider);
+ SkylarkProviders skylarkProviders =
+ new SkylarkProviders(
+ ImmutableMap.<String, Object>of(),
+ ImmutableMap.of(SkylarkRuleContext.getDefaultProvider().getKey(), defaultProvider));
TransitiveInfoProviderMap.Builder builder =
TransitiveInfoProviderMap.builder()
.put(VisibilityProvider.class, this)
.put(LicensesProvider.class, this)
- .add(new FileProvider(filesToBuild))
- .add(FilesToRunProvider.fromSingleExecutableArtifact(artifact));
+ .put(SkylarkProviders.class, skylarkProviders)
+ .add(fileProvider)
+ .add(filesToRunProvider);
if (this instanceof FilesetProvider) {
builder.put(FilesetProvider.class, this);
}
@@ -86,6 +98,6 @@
@Nullable
@Override
public SkylarkClassObject get(ClassObjectConstructor.Key providerKey) {
- return null;
+ return getProvider(SkylarkProviders.class).getDeclaredProvider(providerKey);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
index 51954c13..7ba2eff 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupProvider.java
@@ -53,7 +53,7 @@
@Immutable
public final class OutputGroupProvider implements
TransitiveInfoProvider, SkylarkIndexable, Iterable<String> {
- public static String SKYLARK_NAME = "output_groups";
+ public static final String SKYLARK_NAME = "output_groups";
/**
* Prefix for output groups that are not reported to the user on the terminal output of Blaze when
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
index 9bab046..077e2ec 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java
@@ -92,7 +92,6 @@
getFilesToRun(runfilesSupport, filesToBuild), runfilesSupport, executable);
addProvider(new FileProvider(filesToBuild));
addProvider(filesToRunProvider);
- addSkylarkTransitiveInfo(FilesToRunProvider.SKYLARK_NAME, filesToRunProvider);
if (runfilesSupport != null) {
// If a binary is built, build its runfiles, too
@@ -136,6 +135,14 @@
addSkylarkTransitiveInfo(OutputGroupProvider.SKYLARK_NAME, outputGroupProvider);
}
+ // Populate default provider fields and build it
+ DefaultProvider defaultProvider =
+ DefaultProvider.build(
+ providersBuilder.getProvider(RunfilesProvider.class),
+ providersBuilder.getProvider(FileProvider.class),
+ filesToRunProvider);
+ skylarkDeclaredProviders.put(defaultProvider.getConstructor().getKey(), defaultProvider);
+
TransitiveInfoProviderMap providers = providersBuilder.build();
addRegisteredProvidersToSkylarkProviders(providers);