aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-06-21 10:13:53 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-06-21 10:15:17 -0700
commitdcd0abc97b8372949b592aae817e5ad12f040ab4 (patch)
tree0e56c9677a0044795a0c4d5d4b92838a67db2032
parent5728af65e8b89b9dd3a5ac2b717c93ec5333ca18 (diff)
Migrate DefaultInfo and its provider to skylarkbuildapi
RELNOTES: None. PiperOrigin-RevId: 201544076
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/DefaultInfo.java173
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java72
-rw-r--r--src/main/java/com/google/devtools/build/lib/packages/NativeInfo.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/DefaultInfoApi.java164
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java7
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java22
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java3
10 files changed, 358 insertions, 135 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DefaultInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/DefaultInfo.java
index 642410567d..4da947e0bd 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DefaultInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DefaultInfo.java
@@ -13,90 +13,145 @@
// limitations under the License.
package com.google.devtools.build.lib.analysis;
-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.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.BuiltinProvider;
import com.google.devtools.build.lib.packages.NativeInfo;
-import com.google.devtools.build.lib.packages.NativeProvider;
-import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.skylarkbuildapi.DefaultInfoApi;
+import com.google.devtools.build.lib.skylarkbuildapi.FilesToRunProviderApi;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.Runtime;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nullable;
/** DefaultInfo is provided by all targets implicitly and contains all standard fields. */
@Immutable
-public final class DefaultInfo extends NativeInfo {
-
- // 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 static final ImmutableList<String> KEYS =
- ImmutableList.of(
- DATA_RUNFILES_FIELD,
- DEFAULT_RUNFILES_FIELD,
- FILES_FIELD,
- FilesToRunProvider.SKYLARK_NAME);
-
- private final RunfilesProvider runfilesProvider;
- private final FileProvider fileProvider;
+public final class DefaultInfo extends NativeInfo implements DefaultInfoApi {
+
+ private final SkylarkNestedSet files;
+ private final Runfiles runfiles;
+ private final Runfiles dataRunfiles;
+ private final Runfiles defaultRunfiles;
+ private final Artifact executable;
private final FilesToRunProvider filesToRunProvider;
- private final AtomicReference<SkylarkNestedSet> files = new AtomicReference<>();
-
- public static final String SKYLARK_NAME = "DefaultInfo";
-
- // todo(dslomov,vladmos): make this provider return DefaultInfo.
- public static final NativeProvider<NativeInfo> PROVIDER =
- new NativeProvider<NativeInfo>(NativeInfo.class, SKYLARK_NAME) {
- @Override
- protected NativeInfo createInstanceFromSkylark(
- Object[] args, Environment env, Location loc) {
- @SuppressWarnings("unchecked")
- Map<String, Object> kwargs = (Map<String, Object>) args[0];
- return new NativeInfo(this, kwargs, loc);
- }
- };
+
+ /**
+ * Singleton instance of the provider type for {@link DefaultInfo}.
+ */
+ public static final DefaultInfoProvider PROVIDER = new DefaultInfoProvider();
private DefaultInfo(
- RunfilesProvider runfilesProvider,
+ @Nullable RunfilesProvider runfilesProvider,
FileProvider fileProvider,
FilesToRunProvider filesToRunProvider) {
- super(PROVIDER);
- this.runfilesProvider = runfilesProvider;
- this.fileProvider = fileProvider;
+ this(
+ Location.BUILTIN,
+ SkylarkNestedSet.of(Artifact.class, fileProvider.getFilesToBuild()),
+ Runfiles.EMPTY,
+ (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDataRunfiles(),
+ (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDefaultRunfiles(),
+ filesToRunProvider.getExecutable(),
+ filesToRunProvider
+ );
+ }
+
+ private DefaultInfo(
+ Location loc,
+ SkylarkNestedSet files, Runfiles runfiles,
+ Runfiles dataRunfiles, Runfiles defaultRunfiles, Artifact executable,
+ @Nullable FilesToRunProvider filesToRunProvider) {
+ super(PROVIDER, loc);
+ this.files = files;
+ this.runfiles = runfiles;
+ this.dataRunfiles = dataRunfiles;
+ this.defaultRunfiles = defaultRunfiles;
+ this.executable = executable;
this.filesToRunProvider = filesToRunProvider;
}
public static DefaultInfo build(
- RunfilesProvider runfilesProvider,
+ @Nullable RunfilesProvider runfilesProvider,
FileProvider fileProvider,
FilesToRunProvider filesToRunProvider) {
return new DefaultInfo(runfilesProvider, fileProvider, filesToRunProvider);
}
@Override
- public Object getValue(String name) {
- switch (name) {
- case DATA_RUNFILES_FIELD:
- return (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDataRunfiles();
- case DEFAULT_RUNFILES_FIELD:
- return (runfilesProvider == null) ? Runfiles.EMPTY : runfilesProvider.getDefaultRunfiles();
- case FILES_FIELD:
- if (files.get() == null) {
- files.compareAndSet(
- null, SkylarkNestedSet.of(Artifact.class, fileProvider.getFilesToBuild()));
- }
- return files.get();
- case FilesToRunProvider.SKYLARK_NAME:
- return filesToRunProvider;
- }
- return null;
+ public SkylarkNestedSet getFiles() {
+ return files;
+ }
+
+ @Override
+ public FilesToRunProviderApi getFilesToRun() {
+ return filesToRunProvider;
+ }
+
+ /**
+ * Returns a set of runfiles acting as both the data runfiles and the default runfiles.
+ *
+ * This is kept for legacy reasons.
+ */
+ public Runfiles getStatelessRunfiles() {
+ return runfiles;
+ }
+
+ @Override
+ public Runfiles getDataRunfiles() {
+ return dataRunfiles;
}
@Override
- public ImmutableCollection<String> getFieldNames() {
- return KEYS;
+ public Runfiles getDefaultRunfiles() {
+ return defaultRunfiles;
+ }
+
+ /**
+ * If the rule producing this info object is marked 'executable' or 'test', this is an artifact
+ * representing the file that should be executed to run the target. This is null otherwise.
+ */
+ public Artifact getExecutable() {
+ return executable;
+ }
+
+ /**
+ * Provider implementation for {@link DefaultInfoApi}.
+ */
+ public static class DefaultInfoProvider extends BuiltinProvider<DefaultInfo>
+ implements DefaultInfoApi.DefaultInfoApiProvider<Runfiles, Artifact> {
+ private DefaultInfoProvider() {
+ super("DefaultInfo", DefaultInfo.class);
+ }
+
+ @Override
+ public DefaultInfo constructor(Object files, Object runfilesObj,
+ Object dataRunfilesObj, Object defaultRunfilesObj, Object executable, Location loc)
+ throws EvalException {
+
+ Runfiles statelessRunfiles = castNoneToNull(Runfiles.class, runfilesObj);
+ Runfiles dataRunfiles = castNoneToNull(Runfiles.class, dataRunfilesObj);
+ Runfiles defaultRunfiles = castNoneToNull(Runfiles.class, defaultRunfilesObj);
+
+ if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
+ throw new EvalException(loc, "Cannot specify the provider 'runfiles' "
+ + "together with 'data_runfiles' or 'default_runfiles'");
+ }
+
+ return new DefaultInfo(
+ loc,
+ castNoneToNull(SkylarkNestedSet.class, files),
+ statelessRunfiles,
+ dataRunfiles,
+ defaultRunfiles,
+ castNoneToNull(Artifact.class, executable), null);
+ }
+ }
+
+ private static <T> T castNoneToNull(Class<T> clazz, Object value) {
+ if (value == Runtime.NONE) {
+ return null;
+ } else {
+ return clazz.cast(value);
+ }
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
index 18aa071b6d..ac626b32ca 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/AbstractConfiguredTarget.java
@@ -209,11 +209,13 @@ public abstract class AbstractConfiguredTarget
}
switch (providerKey) {
case FILES_FIELD:
+ return getDefaultProvider().getFiles();
case DEFAULT_RUNFILES_FIELD:
+ return getDefaultProvider().getDefaultRunfiles();
case DATA_RUNFILES_FIELD:
+ return getDefaultProvider().getDataRunfiles();
case FilesToRunProvider.SKYLARK_NAME:
- // Standard fields should be proxied to their default provider object
- return getDefaultProvider().getValue(providerKey);
+ return getDefaultProvider().getFilesToRun();
case OutputGroupInfo.SKYLARK_NAME:
return get(OutputGroupInfo.SKYLARK_CONSTRUCTOR);
default:
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
index 9f50d75077..a71bdab7ad 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.analysis.skylark;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ActionsProvider;
+import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.packages.SkylarkNativeModule;
import com.google.devtools.build.lib.packages.StructProvider;
@@ -40,7 +41,8 @@ public final class SkylarkModules {
SkylarkRuleClassFunctions.class,
StructProvider.STRUCT,
OutputGroupInfo.SKYLARK_CONSTRUCTOR,
- ActionsProvider.INSTANCE);
+ ActionsProvider.INSTANCE,
+ DefaultInfo.PROVIDER);
/**
* Adds bindings for skylark built-ins and non-rules-specific globals of the build API to
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
index 410882456c..249c6b6ab2 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleClassFunctions.java
@@ -34,7 +34,6 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.BaseRuleClasses;
-import com.google.devtools.build.lib.analysis.DefaultInfo;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.config.ConfigAwareRuleClassBuilder;
import com.google.devtools.build.lib.analysis.config.HostTransition;
@@ -49,7 +48,6 @@ import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.AttributeValueSource;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SkylarkImplicitOutputsFunctionWithCallback;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SkylarkImplicitOutputsFunctionWithMap;
-import com.google.devtools.build.lib.packages.NativeProvider;
import com.google.devtools.build.lib.packages.Package.NameConflictException;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.PackageFactory.PackageContext;
@@ -72,7 +70,6 @@ import com.google.devtools.build.lib.packages.TestSize;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkbuildapi.SkylarkRuleFunctionsApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
import com.google.devtools.build.lib.syntax.BaseFunction;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
@@ -219,43 +216,6 @@ public class SkylarkRuleClassFunctions implements SkylarkRuleFunctionsApi<Artifa
}
};
- @SkylarkSignature(
- name = "DefaultInfo",
- returnType = Provider.class,
- doc =
- "A provider that gives general information about a target's direct and transitive files. "
- + "Every rule type has this provider, even if it is not returned explicitly by the "
- + "rule's implementation function."
- + "<p>The <code>DefaultInfo</code> constructor accepts the following parameters:"
- + "<ul>"
- + "<li><code>executable</code>: If this rule is marked "
- + "<a href='globals.html#rule.executable'><code>executable</code></a> or "
- + "<a href='globals.html#rule.test'><code>test</code></a>, this is a "
- + "<a href='File.html'><code>File</code></a> object representing the file that should "
- + "be executed to run the target. By default it is the predeclared output "
- + "<code>ctx.outputs.executable</code>."
- + "<li><code>files</code>: A <a href='depset.html'><code>depset</code></a> of "
- + "<a href='File.html'><code>File</code></a> objects representing the default outputs "
- + "to build when this target is specified on the blaze command line. By default it is "
- + "all predeclared outputs."
- + "<li><code>runfiles</code>: set of files acting as both the "
- + "<code>data_runfiles</code> and <code>default_runfiles</code>."
- + "<li><code>data_runfiles</code>: are the files that are added to the runfiles of a "
- + "target that depends on the rule via the <code>data</code> attribute."
- + "<li><code>default_runfiles</code>: are the files that are added to the runfiles of "
- + "a target that depends on the rule via anything but the <code>data</code> attribute."
- + "</ul>"
- + "Each <code>DefaultInfo</code> instance has the following fields: "
- + "<ul>"
- + "<li><code>files</code>"
- + "<li><code>files_to_run</code>"
- + "<li><code>data_runfiles</code>"
- + "<li><code>default_runfiles</code>"
- + "</ul>"
- + "See the <a href='../rules.$DOC_EXT'>rules</a> page for more information."
- )
- private static final NativeProvider<?> defaultInfo = DefaultInfo.PROVIDER;
-
@Override
public Provider provider(String doc, Object fields, Location location) throws EvalException {
Iterable<String> fieldNames = null;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
index e0182e26c9..1f2a184844 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleConfiguredTargetUtil.java
@@ -397,34 +397,53 @@ public final class SkylarkRuleConfiguredTargetUtil {
Location loc = provider.getCreationLoc();
- for (String field : provider.getFieldNames()) {
- if (field.equals("files")) {
- files = cast("files", provider, SkylarkNestedSet.class, Artifact.class, loc);
- } else if (field.equals("runfiles")) {
- statelessRunfiles = cast("runfiles", provider, Runfiles.class, loc);
- } else if (field.equals("data_runfiles")) {
- dataRunfiles = cast("data_runfiles", provider, Runfiles.class, loc);
- } else if (field.equals("default_runfiles")) {
- defaultRunfiles = cast("default_runfiles", provider, Runfiles.class, loc);
- } else if (field.equals("executable")) {
- executable = cast("executable", provider, Artifact.class, loc);
- if (!executable.getArtifactOwner().equals(context.getRuleContext().getOwner())) {
- throw new EvalException(
- loc,
- String.format(
- "'executable' provided by an executable rule '%s' should be created "
- + "by the same rule.",
- context.getRuleContext().getRule().getRuleClass()));
+ if (provider
+ .getProvider()
+ .getKey()
+ .equals(DefaultInfo.PROVIDER.getKey())) {
+ DefaultInfo defaultInfo = (DefaultInfo) provider;
+
+ files = defaultInfo.getFiles();
+ statelessRunfiles = defaultInfo.getStatelessRunfiles();
+ dataRunfiles = defaultInfo.getDataRunfiles();
+ defaultRunfiles = defaultInfo.getDefaultRunfiles();
+ executable = defaultInfo.getExecutable();
+
+ } else {
+ // Rule implementations aren't reqiured to return default-info fields via a DefaultInfo
+ // provider. They can return them as fields on the returned struct. For example,
+ // 'return struct(executable = foo)' instead of 'return DefaultInfo(executable = foo)'.
+ // TODO(cparsons): Look into deprecating this option.
+ for (String field : provider.getFieldNames()) {
+ if (field.equals("files")) {
+ files = cast("files", provider, SkylarkNestedSet.class, Artifact.class, loc);
+ } else if (field.equals("runfiles")) {
+ statelessRunfiles = cast("runfiles", provider, Runfiles.class, loc);
+ } else if (field.equals("data_runfiles")) {
+ dataRunfiles = cast("data_runfiles", provider, Runfiles.class, loc);
+ } else if (field.equals("default_runfiles")) {
+ defaultRunfiles = cast("default_runfiles", provider, Runfiles.class, loc);
+ } else if (field.equals("executable") && provider.getValue("executable") != null) {
+ executable = cast("executable", provider, Artifact.class, loc);
}
- } else if (provider
- .getProvider()
- .getKey()
- .equals(DefaultInfo.PROVIDER.getKey())) {
- // Custom fields are not allowed for default providers
- throw new EvalException(loc, "Invalid field for default provider: " + field);
+ }
+
+ if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
+ throw new EvalException(loc, "Cannot specify the provider 'runfiles' "
+ + "together with 'data_runfiles' or 'default_runfiles'");
}
}
+ if (executable != null
+ && !executable.getArtifactOwner().equals(context.getRuleContext().getOwner())) {
+ throw new EvalException(
+ loc,
+ String.format(
+ "'executable' provided by an executable rule '%s' should be created "
+ + "by the same rule.",
+ context.getRuleContext().getRule().getRuleClass()));
+ }
+
if (executable != null && context.isExecutable() && context.isDefaultExecutableCreated()) {
Artifact defaultExecutable = context.getRuleContext().createOutputArtifact();
if (!executable.equals(defaultExecutable)) {
@@ -487,11 +506,6 @@ public final class SkylarkRuleConfiguredTargetUtil {
builder.setFilesToBuild(files.getSet(Artifact.class));
}
- if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
- throw new EvalException(loc, "Cannot specify the provider 'runfiles' "
- + "together with 'data_runfiles' or 'default_runfiles'");
- }
-
if (statelessRunfiles == null && dataRunfiles == null && defaultRunfiles == null) {
// No runfiles specified, set default
statelessRunfiles = Runfiles.EMPTY;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/NativeInfo.java b/src/main/java/com/google/devtools/build/lib/packages/NativeInfo.java
index 186a0d473e..3798b1fc79 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/NativeInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/NativeInfo.java
@@ -75,7 +75,7 @@ public class NativeInfo extends Info {
this(provider, ImmutableMap.of(), loc);
}
- // TODO(cparsons): Remove this constructor once DefaultInfo and ToolchainInfo stop using it.
+ // TODO(cparsons): Remove this constructor once ToolchainInfo stops using it.
@Deprecated
public NativeInfo(Provider provider, Map<String, Object> values, Location loc) {
super(provider, loc);
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/DefaultInfoApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/DefaultInfoApi.java
new file mode 100644
index 0000000000..b4a3c2596f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/DefaultInfoApi.java
@@ -0,0 +1,164 @@
+// Copyright 2018 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.skylarkbuildapi;
+
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkinterface.Param;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkConstructor;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+
+/** A provider that gives general information about a target's direct and transitive files. */
+@SkylarkModule(
+ name = "DefaultInfo",
+ category = SkylarkModuleCategory.PROVIDER,
+ doc = "A provider that gives general information about a target's direct and transitive files. "
+ + "Every rule type has this provider, even if it is not returned explicitly by the "
+ + "rule's implementation function."
+ + "Each <code>DefaultInfo</code> instance has the following fields: "
+ + "<ul>"
+ + "<li><code>files</code>"
+ + "<li><code>files_to_run</code>"
+ + "<li><code>data_runfiles</code>"
+ + "<li><code>default_runfiles</code>"
+ + "</ul>"
+ + "See the <a href='../rules.$DOC_EXT'>rules</a> page for more information."
+)
+public interface DefaultInfoApi extends StructApi {
+
+ @SkylarkCallable(
+ name = "files",
+ doc = "A <a href='depset.html'><code>depset</code></a> of "
+ + "<a href='File.html'><code>File</code></a> objects representing the default "
+ + "outputs to build when this target is specified on the blaze command line. By "
+ + "default it is all predeclared outputs.",
+ structField = true,
+ allowReturnNones = true
+ )
+ SkylarkNestedSet getFiles();
+
+ @SkylarkCallable(
+ name = "files_to_run",
+ doc = "A <a href='FilesToRunProvider.html'><code>FilesToRunProvider</code></a> object "
+ + "containing information about the executable and runfiles of the target.",
+ structField = true,
+ allowReturnNones = true
+ )
+ FilesToRunProviderApi<?> getFilesToRun();
+
+ @SkylarkCallable(
+ name = "data_runfiles",
+ doc = "the files that are added to the runfiles of a "
+ + "target that depend on the rule via the <code>data</code> attribute.",
+ structField = true,
+ allowReturnNones = true
+ )
+ RunfilesApi getDataRunfiles();
+
+ @SkylarkCallable(
+ name = "default_runfiles",
+ doc = "the files that are added to the runfiles of "
+ + "a target that depend on the rule via anything but the <code>data</code> "
+ + "attribute.",
+ structField = true,
+ allowReturnNones = true
+ )
+ RunfilesApi getDefaultRunfiles();
+
+ /**
+ * Provider for {@link DefaultInfoApi}.
+ */
+ @SkylarkModule(name = "Provider", documented = false, doc = "")
+ public static interface DefaultInfoApiProvider<RunfilesT extends RunfilesApi,
+ FileT extends FileApi> extends ProviderApi {
+
+ @SkylarkCallable(
+ name = "DefaultInfo",
+ doc = "<p>The <code>DefaultInfo</code> constructor.",
+ parameters = {
+ @Param(
+ name = "files",
+ type = SkylarkNestedSet.class,
+ named = true,
+ positional = false,
+ defaultValue = "None",
+ noneable = true,
+ doc = "A <a href='depset.html'><code>depset</code></a> of "
+ + "<a href='File.html'><code>File</code></a> objects representing the default "
+ + "outputs to build when this target is specified on the blaze command line. By "
+ + "default it is all predeclared outputs."
+ ),
+ @Param(
+ name = "runfiles",
+ type = RunfilesApi.class,
+ named = true,
+ positional = false,
+ defaultValue = "None",
+ noneable = true,
+ doc = "set of files acting as both the "
+ + "<code>data_runfiles</code> and <code>default_runfiles</code>."
+ ),
+ @Param(
+ name = "data_runfiles",
+ type = RunfilesApi.class,
+ named = true,
+ positional = false,
+ defaultValue = "None",
+ noneable = true,
+ doc = "the files that are added to the runfiles of a "
+ + "target that depend on the rule via the <code>data</code> attribute."
+ ),
+ @Param(
+ name = "default_runfiles",
+ type = RunfilesApi.class,
+ named = true,
+ positional = false,
+ defaultValue = "None",
+ noneable = true,
+ doc = "the files that are added to the runfiles of "
+ + "a target that depend on the rule via anything but the <code>data</code> "
+ + "attribute."
+ ),
+ @Param(
+ name = "executable",
+ type = FileApi.class,
+ named = true,
+ positional = false,
+ defaultValue = "None",
+ noneable = true,
+ doc = "If this rule is marked "
+ + "<a href='globals.html#rule.executable'><code>executable</code></a> or "
+ + "<a href='globals.html#rule.test'><code>test</code></a>, this is a "
+ + "<a href='File.html'><code>File</code></a> object representing the file that "
+ + "should be executed to run the target. By default it is the predeclared output "
+ + "<code>ctx.outputs.executable</code>."
+ )},
+ useLocation = true,
+ selfCall = true)
+ @SkylarkConstructor(objectType = DefaultInfoApi.class,
+ receiverNameForDoc = "DefaultInfo")
+ public DefaultInfoApi constructor(
+ // TODO(cparsons): Use stricter types when Runfiles.NONE is passed as null.
+ Object files,
+ Object runfiles,
+ Object dataRunfiles,
+ Object defaultRunfiles,
+ Object executable,
+ Location loc) throws EvalException;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
index ed0ffec634..002dc41e4c 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/TopLevelBootstrap.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.skylarkbuildapi;
import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.skylarkbuildapi.DefaultInfoApi.DefaultInfoApiProvider;
import com.google.devtools.build.lib.skylarkbuildapi.OutputGroupInfoApi.OutputGroupInfoApiProvider;
import com.google.devtools.build.lib.syntax.Runtime;
@@ -30,6 +31,7 @@ public class TopLevelBootstrap implements Bootstrap {
private final StructApi.StructProviderApi structProvider;
private final OutputGroupInfoApiProvider outputGroupInfoProvider;
private final ActionsInfoProviderApi actionsInfoProviderApi;
+ private final DefaultInfoApiProvider<?, ?> defaultInfoProvider;
public TopLevelBootstrap(
Class<? extends SkylarkBuildApiGlobals> skylarkBuildApiGlobals,
@@ -39,7 +41,8 @@ public class TopLevelBootstrap implements Bootstrap {
Class<? extends SkylarkRuleFunctionsApi<?>> skylarkRuleFunctionsApi,
StructApi.StructProviderApi structProvider,
OutputGroupInfoApiProvider outputGroupInfoProvider,
- ActionsInfoProviderApi actionsInfoProviderApi) {
+ ActionsInfoProviderApi actionsInfoProviderApi,
+ DefaultInfoApiProvider<?, ?> defaultInfoProvider) {
this.skylarkAttrApi = skylarkAttrApi;
this.skylarkBuildApiGlobals = skylarkBuildApiGlobals;
this.skylarkCommandLineApi = skylarkCommandLineApi;
@@ -48,6 +51,7 @@ public class TopLevelBootstrap implements Bootstrap {
this.structProvider = structProvider;
this.outputGroupInfoProvider = outputGroupInfoProvider;
this.actionsInfoProviderApi = actionsInfoProviderApi;
+ this.defaultInfoProvider = defaultInfoProvider;
}
@Override
@@ -60,5 +64,6 @@ public class TopLevelBootstrap implements Bootstrap {
builder.put("struct", structProvider);
builder.put("OutputGroupInfo", outputGroupInfoProvider);
builder.put("Actions", actionsInfoProviderApi);
+ builder.put("DefaultInfo", defaultInfoProvider);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
index 877b1a3f24..234899fbf0 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
@@ -576,7 +576,7 @@ public class SkylarkIntegrationTest extends BuildViewTestCase {
}
@Test
- public void testCannotSpecifyRunfilesWithDataOrDefaultRunfiles() throws Exception {
+ public void testCannotSpecifyRunfilesWithDataOrDefaultRunfiles_struct() throws Exception {
scratch.file(
"test/skylark/extension.bzl",
"def custom_rule_impl(ctx):",
@@ -596,6 +596,26 @@ public class SkylarkIntegrationTest extends BuildViewTestCase {
}
@Test
+ public void testCannotSpecifyRunfilesWithDataOrDefaultRunfiles_defaultInfo() throws Exception {
+ scratch.file(
+ "test/skylark/extension.bzl",
+ "def custom_rule_impl(ctx):",
+ " rf = ctx.runfiles()",
+ " return struct(DefaultInfo(runfiles = rf, default_runfiles = rf))",
+ "",
+ "custom_rule = rule(implementation = custom_rule_impl)");
+
+ checkError(
+ "test/skylark",
+ "cr",
+ "Cannot specify the provider 'runfiles' together with "
+ + "'data_runfiles' or 'default_runfiles'",
+ "load('//test/skylark:extension.bzl', 'custom_rule')",
+ "",
+ "custom_rule(name = 'cr')");
+ }
+
+ @Test
public void testInstrumentedFilesProviderWithCodeCoverageDiabled() throws Exception {
scratch.file(
"test/skylark/extension.bzl",
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
index 0312144c85..1de6ab0899 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleImplementationFunctionsTest.java
@@ -1289,7 +1289,8 @@ public class SkylarkRuleImplementationFunctionsTest extends SkylarkTestCase {
getConfiguredTarget("//test:my_rule");
fail();
} catch (AssertionError expected) {
- assertThat(expected).hasMessageThat().contains("Invalid field for default provider: foo");
+ assertThat(expected).hasMessageThat()
+ .contains("unexpected keyword 'foo' in call to DefaultInfo");
}
}