diff options
author | cparsons <cparsons@google.com> | 2018-05-01 15:53:33 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-01 15:55:17 -0700 |
commit | 6891ebbd7b9356b8ce5f6835e3eb7acd9cf988d7 (patch) | |
tree | 86a394bddcefa069c6fab9001e75d417fc95f497 /src/main/java/com | |
parent | 04808943e1c18ed670535d531a4dd435587d584b (diff) |
Migrate AbstractAction and SkylarkActionFactory to buildapi
RELNOTES: None.
PiperOrigin-RevId: 195011200
Diffstat (limited to 'src/main/java/com')
6 files changed, 1191 insertions, 910 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java index b9eea4edba..d41e7d2dcb 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java +++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java @@ -30,11 +30,9 @@ import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.EventHandler; import com.google.devtools.build.lib.packages.AspectDescriptor; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; -import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; -import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; -import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; +import com.google.devtools.build.lib.skylarkbuildapi.ActionApi; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; -import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.SkylarkDict; import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.syntax.SkylarkNestedSet; @@ -58,22 +56,7 @@ import javax.annotation.concurrent.GuardedBy; */ @Immutable @ThreadSafe -@SkylarkModule( - name = "Action", - category = SkylarkModuleCategory.BUILTIN, - doc = - "An action created during rule analysis." - + "<p>This object is visible for the purpose of testing, and may be obtained from an " - + "<a href=\"globals.html#Actions\">Actions</a> provider. It is normally not necessary " - + "to access <code>Action</code> objects or their fields within a rule's implementation " - + "function. You may instead want to see the " - + "<a href='../rules.$DOC_EXT#actions'>Rules page</a> for a general discussion of how to " - + "use actions when defining custom rules, or the <a href='actions.html'>API reference" - + "</a> for creating actions." - + "<p>Some fields of this object are only applicable for certain kinds of actions. " - + "Fields that are inapplicable are set to <code>None</code>." -) -public abstract class AbstractAction implements Action, SkylarkValue { +public abstract class AbstractAction implements Action, ActionApi { /** * An arbitrary default resource set. Currently 250MB of memory, 50% CPU and 0% of total I/O. */ @@ -302,11 +285,6 @@ public abstract class AbstractAction implements Action, SkylarkValue { + getOutputs() + "]" + ")"; } - @SkylarkCallable( - name = "mnemonic", - structField = true, - doc = "The mnemonic for this action." - ) @Override public abstract String getMnemonic(); @@ -580,68 +558,34 @@ public abstract class AbstractAction implements Action, SkylarkValue { return ImmutableList.of(); } - @SkylarkCallable( - name = "inputs", - doc = "A set of the input files of this action.", - structField = true) + @Override public SkylarkNestedSet getSkylarkInputs() { return SkylarkNestedSet.of(Artifact.class, NestedSetBuilder.wrap( Order.STABLE_ORDER, getInputs())); } - @SkylarkCallable( - name = "outputs", - doc = "A set of the output files of this action.", - structField = true) + @Override public SkylarkNestedSet getSkylarkOutputs() { return SkylarkNestedSet.of(Artifact.class, NestedSetBuilder.wrap( Order.STABLE_ORDER, getOutputs())); } - @SkylarkCallable( - name = "argv", - doc = - "For actions created by <a href=\"actions.html#run\">ctx.actions.run()</a> " - + "or <a href=\"actions.html#run_shell\">ctx.actions.run_shell()</a> an immutable " - + "list of the arguments for the command line to be executed. Note that " - + "for shell actions the first two arguments will be the shell path " - + "and <code>\"-c\"</code>.", - structField = true, - allowReturnNones = true - ) - public SkylarkList<String> getSkylarkArgv() throws CommandLineExpansionException { + @Override + public SkylarkList<String> getSkylarkArgv() throws EvalException { return null; } - @SkylarkCallable( - name = "content", - doc = "For actions created by <a href=\"actions.html#write\">ctx.actions.write()</a> or " - + "<a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a>," - + " the contents of the file to be written.", - structField = true, - allowReturnNones = true) + @Override public String getSkylarkContent() throws IOException { return null; } - @SkylarkCallable( - name = "substitutions", - doc = "For actions created by " - + "<a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a>," - + " an immutable dict holding the substitution mapping.", - structField = true, - allowReturnNones = true) + @Override public SkylarkDict<String, String> getSkylarkSubstitutions() { return null; } - @SkylarkCallable( - name = "env", - structField = true, - doc = "The 'fixed' environment variables for this action. This includes only environment " - + "settings which are explicitly set by the action definition, and thus omits settings " - + "which are only pre-set in the execution environment." - ) + @Override public SkylarkDict<String, String> getEnv() { return SkylarkDict.copyOf(null, env.getFixedEnv()); } diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java index 5532b2223d..6cabc59955 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnAction.java @@ -65,8 +65,10 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.NestedSetView; +import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization; +import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.SkylarkList; import com.google.devtools.build.lib.util.Fingerprint; import com.google.devtools.build.lib.util.LazyString; @@ -229,8 +231,12 @@ public class SpawnAction extends AbstractAction implements ExecutionInfoSpecifie } @Override - public SkylarkList<String> getSkylarkArgv() throws CommandLineExpansionException { - return SkylarkList.createImmutable(getArguments()); + public SkylarkList<String> getSkylarkArgv() throws EvalException { + try { + return SkylarkList.createImmutable(getArguments()); + } catch (CommandLineExpansionException exception) { + throw new EvalException(Location.BUILTIN, exception); + } } @Override diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java index 731ccf1cbe..4121df20b1 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java @@ -42,13 +42,12 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.packages.TargetUtils; -import com.google.devtools.build.lib.skylarkinterface.Param; -import com.google.devtools.build.lib.skylarkinterface.ParamType; -import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkbuildapi.CommandLineArgsApi; +import com.google.devtools.build.lib.skylarkbuildapi.FileApi; +import com.google.devtools.build.lib.skylarkbuildapi.SkylarkActionFactoryApi; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; -import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.BaseFunction; import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.EvalException; @@ -71,14 +70,7 @@ import java.util.UUID; import javax.annotation.Nullable; /** Provides a Skylark interface for all action creation needs. */ -@SkylarkModule( - name = "actions", - category = SkylarkModuleCategory.BUILTIN, - doc = - "Module providing functions to create actions. " - + "Access this module using <a href=\"ctx.html#actions\"><code>ctx.actions</code></a>." -) -public class SkylarkActionFactory implements SkylarkValue { +public class SkylarkActionFactory implements SkylarkActionFactoryApi { private final SkylarkRuleContext context; private final SkylarkSemantics skylarkSemantics; private RuleContext ruleContext; @@ -100,44 +92,7 @@ public class SkylarkActionFactory implements SkylarkValue { : ruleContext.getBinOrGenfilesDirectory(); } - @SkylarkCallable( - name = "declare_file", - doc = - "Declares that the rule or aspect creates a file with the given filename. " - + "If <code>sibling</code> is not specified, the file name is relative to the package" - + "directory, otherwise the file is in the same directory as <code>sibling</code>." - + "Files cannot be created outside of the current package." - + "<p>Remember that in addition to declaring a file, you must separately create an " - + "action that emits the file. Creating that action will require passing the returned " - + "<code>File</code> object to the action's construction function." - + "<p>Note that <a href='../rules.$DOC_EXT#files'>predeclared output files</a> do not " - + "need to be (and cannot be) declared using this function. You can obtain their " - + "<code>File</code> objects from <a href=\"ctx.html#outputs\"><code>ctx.outputs</code>" - + "</a> instead. " - + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" - + "computed_dependencies/hash.bzl\">See example of use</a>", - parameters = { - @Param( - name = "filename", - type = String.class, - doc = - "If no 'sibling' provided, path of the new file, relative " - + "to the current package. Otherwise a base name for a file " - + "('sibling' determines a directory)." - ), - @Param( - name = "sibling", - doc = - "A file that lives in the same directory as the newly created file. " - + "The file must be in the current package.", - type = Artifact.class, - noneable = true, - positional = false, - named = true, - defaultValue = "None" - ) - } - ) + @Override public Artifact declareFile(String filename, Object sibling) throws EvalException { context.checkMutable("actions.declare_file"); if (Runtime.NONE.equals(sibling)) { @@ -149,31 +104,7 @@ public class SkylarkActionFactory implements SkylarkValue { } } - @SkylarkCallable( - name = "declare_directory", - doc = - "Declares that rule or aspect create a directory with the given name, in the " - + "current package. You must create an action that generates the directory.", - parameters = { - @Param( - name = "filename", - type = String.class, - doc = - "If no 'sibling' provided, path of the new directory, relative " - + "to the current package. Otherwise a base name for a file " - + "('sibling' defines a directory)." - ), - @Param( - name = "sibling", - doc = "A file that lives in the same directory as the newly declared directory.", - type = Artifact.class, - noneable = true, - positional = false, - named = true, - defaultValue = "None" - ) - } - ) + @Override public Artifact declareDirectory(String filename, Object sibling) throws EvalException { context.checkMutable("actions.declare_directory"); if (Runtime.NONE.equals(sibling)) { @@ -186,34 +117,7 @@ public class SkylarkActionFactory implements SkylarkValue { } } - - @SkylarkCallable( - name = "do_nothing", - doc = - "Creates an empty action that neither executes a command nor produces any " - + "output, but that is useful for inserting 'extra actions'.", - parameters = { - @Param( - name = "mnemonic", - type = String.class, - named = true, - positional = false, - doc = "A one-word description of the action, for example, CppCompile or GoLink." - ), - @Param( - name = "inputs", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - generic1 = Artifact.class, - named = true, - positional = false, - defaultValue = "[]", - doc = "List of the input files of the action." - ), - } - ) + @Override public void doNothing(String mnemonic, Object inputs) throws EvalException { context.checkMutable("actions.do_nothing"); NestedSet<Artifact> inputSet = inputs instanceof SkylarkNestedSet @@ -235,45 +139,19 @@ public class SkylarkActionFactory implements SkylarkValue { ruleContext.registerAction(action); } - @SkylarkCallable( - name = "write", - doc = - "Creates a file write action. When the action is executed, it will write the given content " - + "to a file. This is used to generate files using information available in the " - + "analysis phase. If the file is large and with a lot of static content, consider " - + "using <a href=\"#expand_template\"><code>expand_template</code></a>.", - parameters = { - @Param(name = "output", type = Artifact.class, doc = "The output file.", named = true), - @Param( - name = "content", - type = Object.class, - allowedTypes = {@ParamType(type = String.class), @ParamType(type = Args.class)}, - doc = - "the contents of the file. " - + "May be a either a string or an " - + "<a href=\"actions.html#args\"><code>actions.args()</code></a> object.", - named = true - ), - @Param( - name = "is_executable", - type = Boolean.class, - defaultValue = "False", - doc = "Whether the output file should be executable.", - named = true - ) - } - ) - public void write(Artifact output, Object content, Boolean isExecutable) throws EvalException { + @Override + public void write(FileApi output, Object content, Boolean isExecutable) throws EvalException { context.checkMutable("actions.write"); final Action action; if (content instanceof String) { - action = FileWriteAction.create(ruleContext, output, (String) content, isExecutable); + action = + FileWriteAction.create(ruleContext, (Artifact) output, (String) content, isExecutable); } else if (content instanceof Args) { Args args = (Args) content; action = new ParameterFileWriteAction( ruleContext.getActionOwner(), - output, + (Artifact) output, args.build(), args.parameterFileType, StandardCharsets.UTF_8); @@ -283,138 +161,7 @@ public class SkylarkActionFactory implements SkylarkValue { ruleContext.registerAction(action); } - @SkylarkCallable( - name = "run", - doc = - "Creates an action that runs an executable. " - + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" - + "actions_run/execute.bzl\">See example of use</a>", - parameters = { - @Param( - name = "outputs", - type = SkylarkList.class, - generic1 = Artifact.class, - named = true, - positional = false, - doc = "List of the output files of the action." - ), - @Param( - name = "inputs", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - generic1 = Artifact.class, - defaultValue = "[]", - named = true, - positional = false, - doc = "List or depset of the input files of the action." - ), - @Param( - name = "executable", - type = Object.class, - allowedTypes = { - @ParamType(type = Artifact.class), - @ParamType(type = String.class), - }, - named = true, - positional = false, - doc = "The executable file to be called by the action." - ), - @Param( - name = "tools", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - generic1 = Artifact.class, - defaultValue = "unbound", - named = true, - positional = false, - doc = - "List or depset of any tools needed by the action. Tools are inputs with additional " - + "runfiles that are automatically made available to the action." - ), - @Param( - name = "arguments", - type = Object.class, - allowedTypes = { - @ParamType(type = SkylarkList.class), - }, - defaultValue = "[]", - named = true, - positional = false, - doc = - "Command line arguments of the action. " - + "Must be a list of strings or " - + "<a href=\"actions.html#args\"><code>actions.args()</code></a> objects." - ), - @Param( - name = "mnemonic", - type = String.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = "A one-word description of the action, for example, CppCompile or GoLink." - ), - @Param( - name = "progress_message", - type = String.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "Progress message to show to the user during the build, " - + "for example, \"Compiling foo.cc to create foo.o\"." - ), - @Param( - name = "use_default_shell_env", - type = Boolean.class, - defaultValue = "False", - named = true, - positional = false, - doc = "Whether the action should use the built in shell environment or not." - ), - @Param( - name = "env", - type = SkylarkDict.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = "Sets the dictionary of environment variables." - ), - @Param( - name = "execution_requirements", - type = SkylarkDict.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "Information for scheduling the action. See " - + "<a href=\"$BE_ROOT/common-definitions.html#common.tags\">tags</a> " - + "for useful keys." - ), - @Param( - // TODO(bazel-team): The name here isn't accurate anymore. - // This is technically experimental, so folks shouldn't be too attached, - // but consider renaming to be more accurate/opaque. - name = "input_manifests", - type = SkylarkList.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "(Experimental) sets the input runfiles metadata; " - + "they are typically generated by resolve_command." - ) - }, - useLocation = true - ) + @Override public void run( SkylarkList outputs, Object inputs, @@ -485,148 +232,7 @@ public class SkylarkActionFactory implements SkylarkValue { return ruleContext; } - @SkylarkCallable( - name = "run_shell", - doc = - "Creates an action that runs a shell command. " - + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" - + "shell_command/size.bzl\">See example of use</a>", - parameters = { - @Param( - name = "outputs", - type = SkylarkList.class, - generic1 = Artifact.class, - named = true, - positional = false, - doc = "List of the output files of the action." - ), - @Param( - name = "inputs", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - generic1 = Artifact.class, - defaultValue = "[]", - named = true, - positional = false, - doc = "List or depset of the input files of the action." - ), - @Param( - name = "tools", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - generic1 = Artifact.class, - defaultValue = "unbound", - named = true, - positional = false, - doc = - "List or depset of any tools needed by the action. Tools are inputs with additional " - + "runfiles that are automatically made available to the action." - ), - @Param( - name = "arguments", - allowedTypes = { - @ParamType(type = SkylarkList.class), - }, - defaultValue = "[]", - named = true, - positional = false, - doc = - "Command line arguments of the action. " - + "Must be a list of strings or " - + "<a href=\"actions.html#args\"><code>actions.args()</code></a> objects.<br>" - + "Blaze passes the elements in this attribute as arguments to the command." - + "The command can access these arguments as <code>$1</code>, <code>$2</code>, etc." - ), - @Param( - name = "mnemonic", - type = String.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = "A one-word description of the action, for example, CppCompile or GoLink." - ), - @Param( - name = "command", - type = Object.class, - allowedTypes = { - @ParamType(type = String.class), - @ParamType(type = SkylarkList.class, generic1 = String.class), - @ParamType(type = Runtime.NoneType.class), - }, - named = true, - positional = false, - doc = - "Shell command to execute.<br><br>" - + "<b>Passing a sequence of strings to this attribute is deprecated and Blaze may " - + "stop accepting such values in the future.</b><br><br>" - + "The command can access the elements of the <code>arguments</code> object via " - + "<code>$1</code>, <code>$2</code>, etc.<br>" - + "When this argument is a string, it must be a valid shell command. For example: " - + "\"<code>echo foo > $1</code>\". Blaze uses the same shell to execute the " - + "command as it does for genrules." - ), - @Param( - name = "progress_message", - type = String.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "Progress message to show to the user during the build, " - + "for example, \"Compiling foo.cc to create foo.o\"." - ), - @Param( - name = "use_default_shell_env", - type = Boolean.class, - defaultValue = "False", - named = true, - positional = false, - doc = "Whether the action should use the built in shell environment or not." - ), - @Param( - name = "env", - type = SkylarkDict.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = "Sets the dictionary of environment variables." - ), - @Param( - name = "execution_requirements", - type = SkylarkDict.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "Information for scheduling the action. See " - + "<a href=\"$BE_ROOT/common-definitions.html#common.tags\">tags</a> " - + "for useful keys." - ), - @Param( - // TODO(bazel-team): The name here isn't accurate anymore. - // This is technically experimental, so folks shouldn't be too attached, - // but consider renaming to be more accurate/opaque. - name = "input_manifests", - type = SkylarkList.class, - noneable = true, - defaultValue = "None", - named = true, - positional = false, - doc = - "(Experimental) sets the input runfiles metadata; " - + "they are typically generated by resolve_command." - ) - }, - useLocation = true - ) + @Override public void runShell( SkylarkList outputs, Object inputs, @@ -835,52 +441,10 @@ public class SkylarkActionFactory implements SkylarkValue { return mnemonic + "FromSkylark"; } - @SkylarkCallable( - name = "expand_template", - doc = - "Creates a template expansion action. When the action is executed, it will " - + "generate a file based on a template. Parts of the template will be replaced " - + "using the <code>substitutions</code> dictionary. Whenever a key of the " - + "dictionary appears in the template, it is replaced with the associated value. " - + "There is no special syntax for the keys. You may, for example, use curly braces " - + "to avoid conflicts (for example, <code>{KEY}</code>). " - + "<a href=\"https://github.com/bazelbuild/examples/blob/master/rules/expand_template/hello.bzl\">" - + "See example of use</a>", - parameters = { - @Param( - name = "template", - type = Artifact.class, - named = true, - positional = false, - doc = "The template file, which is a UTF-8 encoded text file." - ), - @Param( - name = "output", - type = Artifact.class, - named = true, - positional = false, - doc = "The output file, which is a UTF-8 encoded text file." - ), - @Param( - name = "substitutions", - type = SkylarkDict.class, - named = true, - positional = false, - doc = "Substitutions to make when expanding the template." - ), - @Param( - name = "is_executable", - type = Boolean.class, - defaultValue = "False", - named = true, - positional = false, - doc = "Whether the output file should be executable." - ) - } - ) + @Override public void expandTemplate( - Artifact template, - Artifact output, + FileApi template, + FileApi output, SkylarkDict<?, ?> substitutionsUnchecked, Boolean executable) throws EvalException { @@ -901,8 +465,8 @@ public class SkylarkActionFactory implements SkylarkValue { TemplateExpansionAction action = new TemplateExpansionAction( ruleContext.getActionOwner(), - template, - output, + (Artifact) template, + (Artifact) output, substitutionsBuilder.build(), executable); ruleContext.registerAction(action); @@ -1004,7 +568,7 @@ public class SkylarkActionFactory implements SkylarkValue { + "</pre>" ) @VisibleForTesting - public static class Args extends SkylarkMutable { + public static class Args extends SkylarkMutable implements CommandLineArgsApi { private final Mutability mutability; private final SkylarkSemantics skylarkSemantics; private final SkylarkCustomCommandLine.Builder commandLine; @@ -1012,95 +576,7 @@ public class SkylarkActionFactory implements SkylarkValue { private String flagFormatString; private boolean useAlways; - @SkylarkCallable( - name = "add", - doc = - "Appends an argument to this command line." - + "" - + "<p><b>Deprecation note:</b> The <code>before_each</code>, <code>join_with</code> " - + "and <code>map_fn</code> params are replaced by the <a href='#add_all'><code>" - + "add_all()</code></a> and <a href='#add_joined'><code>add_joined()</code></a> " - + "methods. These parameters will be removed, and are currently disallowed if the " - + "<a href='../backward-compatibility.$DOC_EXT#new-args-api'><code>" - + "--incompatible_disallow_old_style_args_add</code></a> flag is set. Likewise, " - + "<code>value</code> should now be a scalar value, not a list, tuple, or depset of " - + "items.", - parameters = { - @Param( - name = "arg_name_or_value", - doc = - "If two positional parameters are passed this is interpreted as the arg name. " - + "The arg name is added before the value without any processing. " - + "If only one positional parameter is passed, it is interpreted as " - + "<code>value</code> (see below)." - ), - @Param( - name = "value", - defaultValue = "unbound", - doc = - "The object to append. It will be converted to a string using the standard " - + "conversion mentioned above. Since there is no <code>map_each</code> parameter " - + "for this function, <code>value</code> should be either a string or a <code>" - + "File</code>." - + "" - + "<p><i>Deprecated behavior:</i> <code>value</code> may also be a list, tuple, " - + "or depset of multiple items to append." - ), - @Param( - name = "format", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "A format string pattern, to be applied to the stringified version of <code>value" - + "</code>." - + "" - + "<p><i>Deprecated behavior:</i> If <code>value</code> is a list or depset, " - + "formatting is applied to each item." - ), - @Param( - name = "before_each", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " - + "depset. This string will be appended prior to appending each item." - ), - @Param( - name = "join_with", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " - + "depset. All items will be joined together using this string to form a single " - + "arg to append." - ), - @Param( - name = "map_fn", - type = BaseFunction.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " - + "depset. This is a function that transforms the sequence of items into a list " - + "of strings. The sequence of items is given as a positional argument -- the " - + "function must not take any other parameters -- and the returned list's length " - + "must equal the number of items. Use <code>map_each</code> of <code>add_all" - + "</code> or <code>add_joined</code> instead." - ) - }, - useLocation = true - ) + @Override public NoneType addArgument( Object argNameOrValue, Object value, @@ -1169,148 +645,7 @@ public class SkylarkActionFactory implements SkylarkValue { return Runtime.NONE; } - @SkylarkCallable( - name = "add_all", - doc = - "Appends multiple arguments to this command line. For depsets, the items are " - + "evaluated lazily during the execution phase." - + "" - + "<p>Most of the processing occurs over a list of arguments to be appended, as per " - + "the following steps:" - + "<ol>" - + "<li>If <code>map_each</code> is given, it is applied to each input item, and the " - + " resulting lists of strings are concatenated to form the initial argument " - + " list. Otherwise, the initial argument list is the result of applying the " - + " standard conversion to each item." - + "<li>Each argument in the list is formatted with <code>format_each</code>, if " - + " present." - + "<li>If <code>uniquify</code> is true, duplicate arguments are removed. The first " - + " occurrence is the one that remains." - + "<li>If a <code>before_each</code> string is given, it is inserted as a new " - + " argument before each existing argument in the list. This effectively doubles " - + " the number of arguments to be appended by this point." - + "<li>Except in the case that the list is empty and <code>omit_if_empty</code> is " - + " true (the default), the arg name and <code>terminate_with</code> are " - + " inserted as the first and last arguments, respectively, if they are given." - + "</ol>" - + "Note that empty strings are valid arguments that are subject to all these " - + "processing steps.", - parameters = { - @Param( - name = "arg_name_or_values", - doc = - "If two positional parameters are passed this is interpreted as the arg name. " - + "The arg name is added before the <code>values</code> without any processing. " - + "This arg name will not be added if <code>omit_if_empty</code> is true " - + "(the default) and no other items are appended (as happens if " - + "<code>values</code> is empty or all of its items are filtered). " - + "If only one positional parameter is passed, it is interpreted as " - + "<code>values</code> (see below)." - ), - @Param( - name = "values", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - defaultValue = "unbound", - doc = "The list, tuple, or depset whose items will be appended." - ), - @Param( - name = "map_each", - type = BaseFunction.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "A function that converts each item to zero or more strings, which may be further " - + "processed before appending. If this param is not provided, the standard " - + "conversion is used." - + "" - + "<p>The function takes in the item as a positional parameter and must have no " - + "other parameters. The return value's type depends on how many arguments " - + "are to be produced for the item:" - + "<ul>" - + "<li>In the common case when each item turns into one string, the function " - + " should return that string." - + "<li>If the item is to be filtered out entirely, the function should return " - + " <code>None</code>." - + "<li>If the item turns into multiple strings, the function returns a list of " - + " those strings." - + "</ul>" - + "Returning a single string or <code>None</code> has the same effect as " - + "returning a list of length 1 or length 0 respectively. However, it is more " - + "efficient and readable to avoid creating a list where it is not needed." - + "" - + "<p><i>Warning:</i> <a href='globals.html#print'><code>print()</code></a> " - + "statements that are executed during the call to <code>map_each</code> will " - + "not produce any visible output." - ), - @Param( - name = "format_each", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "An optional format string pattern, applied to each string returned by the " - + "<code>map_each</code> function. " - + "The format string must have exactly one '%s' placeholder." - ), - @Param( - name = "before_each", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "An optional string to append before each argument derived from <code>values</code> " - + "is appended." - ), - @Param( - name = "omit_if_empty", - type = Boolean.class, - named = true, - positional = false, - defaultValue = "True", - doc = - "If true, if there are no arguments derived from <code>values</code> to be appended, " - + "then all further processing is suppressed and the command line will be " - + "unchanged. If false, the arg name and <code>terminate_with</code>, " - + "if provided, will still be appended regardless of whether or not there are " - + "other arguments." - ), - @Param( - name = "uniquify", - type = Boolean.class, - named = true, - positional = false, - defaultValue = "False", - doc = - "If true, duplicate arguments that are derived from <code>values</code> will be " - + "omitted. Only the first occurrence of each argument will remain. Usually this " - + "feature is not needed because depsets already omit duplicates, but it can be " - + "useful if <code>map_each</code> emits the same string for multiple items." - ), - @Param( - name = "terminate_with", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "An optional string to append after all other arguments. This string will not be " - + "added if <code>omit_if_empty</code> is true (the default) and no other items " - + "are appended (as happens if <code>values</code> is empty or all of its items " - + "are filtered)." - ), - }, - useLocation = true - ) + @Override public NoneType addAll( Object argNameOrValue, Object values, @@ -1350,111 +685,7 @@ public class SkylarkActionFactory implements SkylarkValue { return Runtime.NONE; } - @SkylarkCallable( - name = "add_joined", - doc = - "Appends an argument to this command line by concatenating together multiple values " - + "using a separator. For depsets, the items are evaluated lazily during the " - + "execution phase." - + "" - + "<p>Processing is similar to <a href='#add_all'><code>add_all()</code></a>, but " - + "the list of arguments derived from <code>values</code> is combined into a single " - + "argument as if by <code>join_with.join(...)</code>, and then formatted using the " - + "given <code>format_joined</code> string template. Unlike <code>add_all()</code>, " - + "there is no <code>before_each</code> or <code>terminate_with</code> parameter " - + "since these are not generally useful when the items are combined into a single " - + "argument." - + "" - + "<p>If after filtering there are no strings to join into an argument, and if " - + "<code>omit_if_empty</code> is true (the default), no processing is done. " - + "Otherwise if there are no strings to join but <code>omit_if_empty</code> is " - + "false, the joined string will be an empty string.", - parameters = { - @Param( - name = "arg_name_or_values", - doc = - "If two positional parameters are passed this is interpreted as the arg name. " - + "The arg name is added before <code>values</code> without any processing. " - + "This arg will not be added if <code>omit_if_empty</code> is true " - + "(the default) and there are no strings derived from <code>values</code> " - + "to join together (which can happen if <code>values</code> is empty " - + "or all of its items are filtered)." - + "If only one positional parameter is passed, it is interpreted as " - + "<code>values</code> (see below)." - ), - @Param( - name = "values", - allowedTypes = { - @ParamType(type = SkylarkList.class), - @ParamType(type = SkylarkNestedSet.class), - }, - defaultValue = "unbound", - doc = "The list, tuple, or depset whose items will be joined." - ), - @Param( - name = "join_with", - type = String.class, - named = true, - positional = false, - doc = - "A delimiter string used to join together the strings obtained from applying " - + "<code>map_each</code> and <code>format_each</code>, in the same manner as " - + "<a href='string.html#join'><code>string.join()</code></a>." - ), - @Param( - name = "map_each", - type = BaseFunction.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = "Same as for <a href='#add_all.map_each'><code>add_all</code></a>." - ), - @Param( - name = "format_each", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = "Same as for <a href='#add_all.format_each'><code>add_all</code></a>." - ), - @Param( - name = "format_joined", - type = String.class, - named = true, - positional = false, - defaultValue = "None", - noneable = true, - doc = - "An optional format string pattern applied to the joined string. " - + "The format string must have exactly one '%s' placeholder." - ), - @Param( - name = "omit_if_empty", - type = Boolean.class, - named = true, - positional = false, - defaultValue = "True", - doc = - "If true, if there are no strings to join together (either because <code>values" - + "</code> is empty or all its items are filtered), then all further processing " - + "is suppressed and the command line will be unchanged. If false, then even if " - + "there are no strings to join together, two arguments will be appended: " - + "the arg name followed by an empty string (which is the logical join " - + "of zero strings)." - ), - @Param( - name = "uniquify", - type = Boolean.class, - named = true, - positional = false, - defaultValue = "False", - doc = "Same as for <a href='#add_all.uniquify'><code>add_all</code></a>." - ) - }, - useLocation = true - ) + @Override public NoneType addJoined( Object argNameOrValue, Object values, @@ -1596,35 +827,7 @@ public class SkylarkActionFactory implements SkylarkValue { } } - @SkylarkCallable( - name = "use_param_file", - doc = - "Spills the args to a params file, replacing them with a pointer to the param file. " - + "Use when your args may be too large for the system's command length limits ", - parameters = { - @Param( - name = "param_file_arg", - type = String.class, - named = true, - doc = - "A format string with a single \"%s\". " - + "If the args are spilled to a params file then they are replaced " - + "with an argument consisting of this string formatted with " - + "the path of the params file." - ), - @Param( - name = "use_always", - type = Boolean.class, - named = true, - positional = false, - defaultValue = "False", - doc = - "Whether to always spill the args to a params file. If false, " - + "bazel will decide whether the arguments need to be spilled " - + "based on your system and arg length." - ) - } - ) + @Override public void useParamsFile(String paramFileArg, Boolean useAlways) throws EvalException { if (isImmutable()) { throw new EvalException(null, "cannot modify frozen value"); @@ -1638,22 +841,7 @@ public class SkylarkActionFactory implements SkylarkValue { this.useAlways = useAlways; } - @SkylarkCallable( - name = "set_param_file_format", - doc = "Sets the format of the param file when written to disk", - parameters = { - @Param( - name = "format", - type = String.class, - named = true, - doc = - "The format of the param file. Must be one of:<br>" - + "\"shell\": All arguments are shell quoted and separated by whitespace<br>" - + "\"multiline\": All arguments are unquoted and separated by newline characters" - + "The format defaults to \"shell\" if not called." - ) - } - ) + @Override public void setParamFileFormat(String format) throws EvalException { if (isImmutable()) { throw new EvalException(null, "cannot modify frozen value"); @@ -1695,11 +883,7 @@ public class SkylarkActionFactory implements SkylarkValue { } } - @SkylarkCallable( - name = "args", - doc = "Returns an Args object that can be used to build memory-efficient command lines.", - useEnvironment = true - ) + @Override public Args args(Environment env) { return new Args(env.mutability(), skylarkSemantics); } diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/ActionApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/ActionApi.java new file mode 100644 index 0000000000..ec38289f58 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/ActionApi.java @@ -0,0 +1,104 @@ +// 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.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; +import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; +import java.io.IOException; + +/** Interface for actions in Skylark. */ +@SkylarkModule( + name = "Action", + category = SkylarkModuleCategory.BUILTIN, + doc = + "An action created during rule analysis." + + "<p>This object is visible for the purpose of testing, and may be obtained from an " + + "<a href=\"globals.html#Actions\">Actions</a> provider. It is normally not necessary " + + "to access <code>Action</code> objects or their fields within a rule's " + + "implementation function. You may instead want to see the " + + "<a href='../rules.$DOC_EXT#actions'>Rules page</a> for a general discussion of how " + + "to use actions when defining custom rules, or the <a href='actions.html'>API " + + "reference</a> for creating actions." + + "<p>Some fields of this object are only applicable for certain kinds of actions. " + + "Fields that are inapplicable are set to <code>None</code>.") +public interface ActionApi extends SkylarkValue { + + @SkylarkCallable( + name = "mnemonic", + structField = true, + doc = "The mnemonic for this action." + ) + public abstract String getMnemonic(); + + @SkylarkCallable( + name = "inputs", + doc = "A set of the input files of this action.", + structField = true) + public SkylarkNestedSet getSkylarkInputs(); + + @SkylarkCallable( + name = "outputs", + doc = "A set of the output files of this action.", + structField = true) + public SkylarkNestedSet getSkylarkOutputs(); + + @SkylarkCallable( + name = "argv", + doc = + "For actions created by <a href=\"actions.html#run\">ctx.actions.run()</a> " + + "or <a href=\"actions.html#run_shell\">ctx.actions.run_shell()</a> an immutable " + + "list of the arguments for the command line to be executed. Note that " + + "for shell actions the first two arguments will be the shell path " + + "and <code>\"-c\"</code>.", + structField = true, + allowReturnNones = true + ) + public SkylarkList<String> getSkylarkArgv() throws EvalException; + + @SkylarkCallable( + name = "content", + doc = + "For actions created by <a href=\"actions.html#write\">ctx.actions.write()</a> or " + + "<a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a>," + + " the contents of the file to be written.", + structField = true, + allowReturnNones = true) + public String getSkylarkContent() throws IOException; + + @SkylarkCallable( + name = "substitutions", + doc = + "For actions created by " + + "<a href=\"actions.html#expand_template\">ctx.actions.expand_template()</a>," + + " an immutable dict holding the substitution mapping.", + structField = true, + allowReturnNones = true) + public SkylarkDict<String, String> getSkylarkSubstitutions(); + + @SkylarkCallable( + name = "env", + structField = true, + doc = + "The 'fixed' environment variables for this action. This includes only environment " + + "settings which are explicitly set by the action definition, and thus omits settings " + + "which are only pre-set in the execution environment.") + public SkylarkDict<String, String> getEnv(); +} diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/CommandLineArgsApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/CommandLineArgsApi.java new file mode 100644 index 0000000000..6d6ba657a8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/CommandLineArgsApi.java @@ -0,0 +1,520 @@ +// 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.ParamType; +import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; +import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.BaseFunction; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.Runtime; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; + +/** Command line args module. */ +@SkylarkModule( + name = "Args", + category = SkylarkModuleCategory.BUILTIN, + doc = + "An object that encapsulates, in a memory-efficient way, the data needed to build part or " + + "all of a command line." + + "" + + "<p>It often happens that an action requires a large command line containing values " + + "accumulated from transitive dependencies. For example, a linker command line might " + + "list every object file needed by all of the libraries being linked. It is best " + + "practice to store such transitive data in <a href='depset.html'><code>depset" + + "</code></a>s, so that they can be shared by multiple targets. However, if the rule " + + "author had to convert these depsets into lists of strings in order to construct an " + + "action command line, it would defeat this memory-sharing optimization." + + "" + + "<p>For this reason, the action-constructing functions accept <code>Args</code> " + + "objects in addition to strings. Each <code>Args</code> object represents a " + + "concatenation of strings and depsets, with optional transformations for " + + "manipulating the data. <code>Args</code> objects do not process the depsets they " + + "encapsulate until the execution phase, when it comes time to calculate the command " + + "line. This helps defer any expensive copying until after the analysis phase is " + + "complete. See the <a href='../performance.$DOC_EXT'>Optimizing Performance</a> page " + + "for more information." + + "" + + "<p><code>Args</code> are constructed by calling <a href='actions.html#args'><code>" + + "ctx.actions.args()</code></a>. They can be passed as the <code>arguments</code> " + + "parameter of <a href='actions.html#run'><code>ctx.actions.run()</code></a> or " + + "<a href='actions.html#run_shell'><code>ctx.actions.run_shell()</code></a>. Each " + + "mutation of an <code>Args</code> object appends values to the eventual command " + + "line." + + "" + + "<p>The <code>map_each</code> feature allows you to customize how items are " + + "transformed into strings. If you do not provide a <code>map_each</code> function, " + + "the standard conversion is as follows: " + + "<ul>" + + "<li>Values that are already strings are left as-is." + + "<li><a href='File.html'><code>File</code></a> objects are turned into their " + + " <code>File.path</code> values." + + "<li>All other types are turned into strings in an <i>unspecified</i> manner. For " + + " this reason, you should avoid passing values that are not of string or " + + " <code>File</code> type to <code>add()</code>, and if you pass them to " + + " <code>add_all()</code> or <code>add_joined()</code> then you should provide a " + + " <code>map_each</code> function." + + "</ul>" + + "" + + "<p>When using string formatting (<code>format</code>, <code>format_each</code>, and " + + "<code>format_joined</code> params of the <code>add*()</code> methods), the format " + + "template is interpreted in the same way as <code>%</code>-substitution on strings, " + + "except that the template must have exactly one substitution placeholder and it must " + + "be <code>%s</code>. Literal percents may be escaped as <code>%%</code>. Formatting " + + "is applied after the value is converted to a string as per the above." + + "" + + "<p>Each of the <code>add*()</code> methods have an alternate form that accepts an " + + "extra positional parameter, an \"arg name\" string to insert before the rest of the " + + "arguments. For <code>add_all</code> and <code>add_joined</code> the extra string " + + "will not be added if the sequence turns out to be empty. " + + "For instance, the same usage can add either <code>--foo val1 val2 val3 --bar" + + "</code> or just <code>--bar</code> to the command line, depending on whether the " + + "given sequence contains <code>val1..val3</code> or is empty." + + "" + + "<p>If the size of the command line can grow longer than the maximum size allowed by " + + "the system, the arguments can be spilled over into parameter files. See " + + "<a href='#use_param_file'><code>use_param_file()</code></a> and " + + "<a href='#set_param_file_format'><code>set_param_file_format()</code></a>." + + "" + + "<p>Example: Suppose we wanted to generate the command line: " + + "<pre>\n" + + "--foo foo1.txt foo2.txt ... fooN.txt --bar bar1.txt,bar2.txt,...,barM.txt --baz\n" + + "</pre>" + + "We could use the following <code>Args</code> object: " + + "<pre class=language-python>\n" + + "# foo_deps and bar_deps are depsets containing\n" + + "# File objects for the foo and bar .txt files.\n" + + "args = ctx.actions.args()\n" + + "args.add_all(\"--foo\", foo_deps)\n" + + "args.add_joined(\"--bar\", bar_deps, join_with=\",\")\n" + + "args.add(\"--baz\")\n" + + "ctx.actions.run(\n" + + " ...\n" + + " arguments = [args],\n" + + " ...\n" + + ")\n" + + "</pre>" +) +public interface CommandLineArgsApi extends SkylarkValue { + @SkylarkCallable( + name = "add", + doc = + "Appends an argument to this command line." + + "" + + "<p><b>Deprecation note:</b> The <code>before_each</code>, <code>join_with</code> " + + "and <code>map_fn</code> params are replaced by the <a href='#add_all'><code>" + + "add_all()</code></a> and <a href='#add_joined'><code>add_joined()</code></a> " + + "methods. These parameters will be removed, and are currently disallowed if the " + + "<a href='../backward-compatibility.$DOC_EXT#new-args-api'><code>" + + "--incompatible_disallow_old_style_args_add</code></a> flag is set. Likewise, " + + "<code>value</code> should now be a scalar value, not a list, tuple, or depset of " + + "items.", + parameters = { + @Param( + name = "arg_name_or_value", + doc = + "If two positional parameters are passed this is interpreted as the arg name. " + + "The arg name is added before the value without any processing. " + + "If only one positional parameter is passed, it is interpreted as " + + "<code>value</code> (see below)."), + @Param( + name = "value", + defaultValue = "unbound", + doc = + "The object to append. It will be converted to a string using the standard " + + "conversion mentioned above. Since there is no <code>map_each</code> parameter " + + "for this function, <code>value</code> should be either a string or a <code>" + + "File</code>." + + "" + + "<p><i>Deprecated behavior:</i> <code>value</code> may also be a list, tuple, " + + "or depset of multiple items to append."), + @Param( + name = "format", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "A format string pattern, to be applied to the stringified version of <code>value" + + "</code>." + + "" + + "<p><i>Deprecated behavior:</i> If <code>value</code> is a list or depset, " + + "formatting is applied to each item."), + @Param( + name = "before_each", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " + + "depset. This string will be appended prior to appending each item."), + @Param( + name = "join_with", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " + + "depset. All items will be joined together using this string to form a single " + + "arg to append."), + @Param( + name = "map_fn", + type = BaseFunction.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "<i>Deprecated:</i> Only supported when <code>value</code> is a list, tuple, or " + + "depset. This is a function that transforms the sequence of items into a list " + + "of strings. The sequence of items is given as a positional argument -- the " + + "function must not take any other parameters -- and the returned list's length " + + "must equal the number of items. Use <code>map_each</code> of <code>add_all" + + "</code> or <code>add_joined</code> instead.") + }, + useLocation = true + ) + public Runtime.NoneType addArgument( + Object argNameOrValue, + Object value, + Object format, + Object beforeEach, + Object joinWith, + Object mapFn, + Location loc) + throws EvalException; + + @SkylarkCallable( + name = "add_all", + doc = + "Appends multiple arguments to this command line. For depsets, the items are " + + "evaluated lazily during the execution phase." + + "" + + "<p>Most of the processing occurs over a list of arguments to be appended, as per " + + "the following steps:" + + "<ol>" + + "<li>If <code>map_each</code> is given, it is applied to each input item, and the " + + " resulting lists of strings are concatenated to form the initial argument " + + " list. Otherwise, the initial argument list is the result of applying the " + + " standard conversion to each item." + + "<li>Each argument in the list is formatted with <code>format_each</code>, if " + + " present." + + "<li>If <code>uniquify</code> is true, duplicate arguments are removed. The first " + + " occurrence is the one that remains." + + "<li>If a <code>before_each</code> string is given, it is inserted as a new " + + " argument before each existing argument in the list. This effectively doubles " + + " the number of arguments to be appended by this point." + + "<li>Except in the case that the list is empty and <code>omit_if_empty</code> is " + + " true (the default), the arg name and <code>terminate_with</code> are " + + " inserted as the first and last arguments, respectively, if they are given." + + "</ol>" + + "Note that empty strings are valid arguments that are subject to all these " + + "processing steps.", + parameters = { + @Param( + name = "arg_name_or_values", + doc = + "If two positional parameters are passed this is interpreted as the arg name. " + + "The arg name is added before the <code>values</code> without any processing. " + + "This arg name will not be added if <code>omit_if_empty</code> is true " + + "(the default) and no other items are appended (as happens if " + + "<code>values</code> is empty or all of its items are filtered). " + + "If only one positional parameter is passed, it is interpreted as " + + "<code>values</code> (see below)." + ), + @Param( + name = "values", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + defaultValue = "unbound", + doc = "The list, tuple, or depset whose items will be appended." + ), + @Param( + name = "map_each", + type = BaseFunction.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "A function that converts each item to zero or more strings, which may be further " + + "processed before appending. If this param is not provided, the standard " + + "conversion is used." + + "" + + "<p>The function takes in the item as a positional parameter and must have no " + + "other parameters. The return value's type depends on how many arguments " + + "are to be produced for the item:" + + "<ul>" + + "<li>In the common case when each item turns into one string, the function " + + " should return that string." + + "<li>If the item is to be filtered out entirely, the function should return " + + " <code>None</code>." + + "<li>If the item turns into multiple strings, the function returns a list of " + + " those strings." + + "</ul>" + + "Returning a single string or <code>None</code> has the same effect as " + + "returning a list of length 1 or length 0 respectively. However, it is more " + + "efficient and readable to avoid creating a list where it is not needed." + + "" + + "<p><i>Warning:</i> <a href='globals.html#print'><code>print()</code></a> " + + "statements that are executed during the call to <code>map_each</code> will " + + "not produce any visible output." + ), + @Param( + name = "format_each", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "An optional format string pattern, applied to each string returned by the " + + "<code>map_each</code> function. " + + "The format string must have exactly one '%s' placeholder." + ), + @Param( + name = "before_each", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "An optional string to append before each argument derived from <code>values</code> " + + "is appended." + ), + @Param( + name = "omit_if_empty", + type = Boolean.class, + named = true, + positional = false, + defaultValue = "True", + doc = + "If true, if there are no arguments derived from <code>values</code> to be " + + "appended, then all further processing is suppressed and the command line will " + + "be unchanged. If false, the arg name and <code>terminate_with</code>, " + + "if provided, will still be appended regardless of whether or not there are " + + "other arguments." + ), + @Param( + name = "uniquify", + type = Boolean.class, + named = true, + positional = false, + defaultValue = "False", + doc = + "If true, duplicate arguments that are derived from <code>values</code> will be " + + "omitted. Only the first occurrence of each argument will remain. Usually this " + + "feature is not needed because depsets already omit duplicates, but it can be " + + "useful if <code>map_each</code> emits the same string for multiple items." + ), + @Param( + name = "terminate_with", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "An optional string to append after all other arguments. This string will not be " + + "added if <code>omit_if_empty</code> is true (the default) and no other items " + + "are appended (as happens if <code>values</code> is empty or all of its items " + + "are filtered)." + ), + }, + useLocation = true + ) + public Runtime.NoneType addAll( + Object argNameOrValue, + Object values, + Object mapEach, + Object formatEach, + Object beforeEach, + Boolean omitIfEmpty, + Boolean uniquify, + Object terminateWith, + Location loc) + throws EvalException; + + @SkylarkCallable( + name = "add_joined", + doc = + "Appends an argument to this command line by concatenating together multiple values " + + "using a separator. For depsets, the items are evaluated lazily during the " + + "execution phase." + + "" + + "<p>Processing is similar to <a href='#add_all'><code>add_all()</code></a>, but " + + "the list of arguments derived from <code>values</code> is combined into a single " + + "argument as if by <code>join_with.join(...)</code>, and then formatted using the " + + "given <code>format_joined</code> string template. Unlike <code>add_all()</code>, " + + "there is no <code>before_each</code> or <code>terminate_with</code> parameter " + + "since these are not generally useful when the items are combined into a single " + + "argument." + + "" + + "<p>If after filtering there are no strings to join into an argument, and if " + + "<code>omit_if_empty</code> is true (the default), no processing is done. " + + "Otherwise if there are no strings to join but <code>omit_if_empty</code> is " + + "false, the joined string will be an empty string.", + parameters = { + @Param( + name = "arg_name_or_values", + doc = + "If two positional parameters are passed this is interpreted as the arg name. " + + "The arg name is added before <code>values</code> without any processing. " + + "This arg will not be added if <code>omit_if_empty</code> is true " + + "(the default) and there are no strings derived from <code>values</code> " + + "to join together (which can happen if <code>values</code> is empty " + + "or all of its items are filtered)." + + "If only one positional parameter is passed, it is interpreted as " + + "<code>values</code> (see below)."), + @Param( + name = "values", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + defaultValue = "unbound", + doc = "The list, tuple, or depset whose items will be joined."), + @Param( + name = "join_with", + type = String.class, + named = true, + positional = false, + doc = + "A delimiter string used to join together the strings obtained from applying " + + "<code>map_each</code> and <code>format_each</code>, in the same manner as " + + "<a href='string.html#join'><code>string.join()</code></a>."), + @Param( + name = "map_each", + type = BaseFunction.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = "Same as for <a href='#add_all.map_each'><code>add_all</code></a>."), + @Param( + name = "format_each", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = "Same as for <a href='#add_all.format_each'><code>add_all</code></a>." + ), + @Param( + name = "format_joined", + type = String.class, + named = true, + positional = false, + defaultValue = "None", + noneable = true, + doc = + "An optional format string pattern applied to the joined string. " + + "The format string must have exactly one '%s' placeholder." + ), + @Param( + name = "omit_if_empty", + type = Boolean.class, + named = true, + positional = false, + defaultValue = "True", + doc = + "If true, if there are no strings to join together (either because <code>values" + + "</code> is empty or all its items are filtered), then all further processing " + + "is suppressed and the command line will be unchanged. If false, then even if " + + "there are no strings to join together, two arguments will be appended: " + + "the arg name followed by an empty string (which is the logical join " + + "of zero strings)." + ), + @Param( + name = "uniquify", + type = Boolean.class, + named = true, + positional = false, + defaultValue = "False", + doc = "Same as for <a href='#add_all.uniquify'><code>add_all</code></a>." + ) + }, + useLocation = true + ) + public Runtime.NoneType addJoined( + Object argNameOrValue, + Object values, + String joinWith, + Object mapEach, + Object formatEach, + Object formatJoined, + Boolean omitIfEmpty, + Boolean uniquify, + Location loc) + throws EvalException; + + @SkylarkCallable( + name = "use_param_file", + doc = + "Spills the args to a params file, replacing them with a pointer to the param file. " + + "Use when your args may be too large for the system's command length limits ", + parameters = { + @Param( + name = "param_file_arg", + type = String.class, + named = true, + doc = + "A format string with a single \"%s\". " + + "If the args are spilled to a params file then they are replaced " + + "with an argument consisting of this string formatted with " + + "the path of the params file."), + @Param( + name = "use_always", + type = Boolean.class, + named = true, + positional = false, + defaultValue = "False", + doc = + "Whether to always spill the args to a params file. If false, " + + "bazel will decide whether the arguments need to be spilled " + + "based on your system and arg length.") + }) + public void useParamsFile(String paramFileArg, Boolean useAlways) throws EvalException; + + @SkylarkCallable( + name = "set_param_file_format", + doc = "Sets the format of the param file when written to disk", + parameters = { + @Param( + name = "format", + type = String.class, + named = true, + doc = + "The format of the param file. Must be one of:<br>" + + "\"shell\": All arguments are shell quoted and separated by whitespace<br>" + + "\"multiline\": All arguments are unquoted and separated by newline characters" + + "The format defaults to \"shell\" if not called.") + } + ) + public void setParamFileFormat(String format) throws EvalException; +} diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java new file mode 100644 index 0000000000..25a3218bc6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkActionFactoryApi.java @@ -0,0 +1,523 @@ +// 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.ParamType; +import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; +import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.Environment; +import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.Runtime; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; + +/** Module providing functions to create actions. */ +@SkylarkModule( + name = "actions", + category = SkylarkModuleCategory.BUILTIN, + doc = + "Module providing functions to create actions. " + + "Access this module using <a href=\"ctx.html#actions\"><code>ctx.actions</code></a>.") +public interface SkylarkActionFactoryApi extends SkylarkValue { + + @SkylarkCallable( + name = "declare_file", + doc = + "Declares that the rule or aspect creates a file with the given filename. " + + "If <code>sibling</code> is not specified, the file name is relative to the package" + + "directory, otherwise the file is in the same directory as <code>sibling</code>." + + "Files cannot be created outside of the current package." + + "<p>Remember that in addition to declaring a file, you must separately create an " + + "action that emits the file. Creating that action will require passing the returned " + + "<code>File</code> object to the action's construction function." + + "<p>Note that <a href='../rules.$DOC_EXT#files'>predeclared output files</a> do not " + + "need to be (and cannot be) declared using this function. You can obtain their " + + "<code>File</code> objects from <a href=\"ctx.html#outputs\"><code>ctx.outputs</code>" + + "</a> instead. " + + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" + + "computed_dependencies/hash.bzl\">See example of use</a>", + parameters = { + @Param( + name = "filename", + type = String.class, + doc = + "If no 'sibling' provided, path of the new file, relative " + + "to the current package. Otherwise a base name for a file " + + "('sibling' determines a directory)." + ), + @Param( + name = "sibling", + doc = + "A file that lives in the same directory as the newly created file. " + + "The file must be in the current package.", + type = FileApi.class, + noneable = true, + positional = false, + named = true, + defaultValue = "None" + ) + } + ) + public FileApi declareFile(String filename, Object sibling) throws EvalException; + + @SkylarkCallable( + name = "declare_directory", + doc = + "Declares that rule or aspect create a directory with the given name, in the " + + "current package. You must create an action that generates the directory.", + parameters = { + @Param( + name = "filename", + type = String.class, + doc = + "If no 'sibling' provided, path of the new directory, relative " + + "to the current package. Otherwise a base name for a file " + + "('sibling' defines a directory)."), + @Param( + name = "sibling", + doc = "A file that lives in the same directory as the newly declared directory.", + type = FileApi.class, + noneable = true, + positional = false, + named = true, + defaultValue = "None") + }) + public FileApi declareDirectory(String filename, Object sibling) throws EvalException; + + @SkylarkCallable( + name = "do_nothing", + doc = + "Creates an empty action that neither executes a command nor produces any " + + "output, but that is useful for inserting 'extra actions'.", + parameters = { + @Param( + name = "mnemonic", + type = String.class, + named = true, + positional = false, + doc = "A one-word description of the action, for example, CppCompile or GoLink."), + @Param( + name = "inputs", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = FileApi.class, + named = true, + positional = false, + defaultValue = "[]", + doc = "List of the input files of the action."), + }) + public void doNothing(String mnemonic, Object inputs) throws EvalException; + + @SkylarkCallable( + name = "write", + doc = + "Creates a file write action. When the action is executed, it will write the given content " + + "to a file. This is used to generate files using information available in the " + + "analysis phase. If the file is large and with a lot of static content, consider " + + "using <a href=\"#expand_template\"><code>expand_template</code></a>.", + parameters = { + @Param(name = "output", type = FileApi.class, doc = "The output file.", named = true), + @Param( + name = "content", + type = Object.class, + allowedTypes = { + @ParamType(type = String.class), + @ParamType(type = CommandLineArgsApi.class) + }, + doc = + "the contents of the file. " + + "May be a either a string or an " + + "<a href=\"actions.html#args\"><code>actions.args()</code></a> object.", + named = true + ), + @Param( + name = "is_executable", + type = Boolean.class, + defaultValue = "False", + doc = "Whether the output file should be executable.", + named = true + ) + } + ) + public void write(FileApi output, Object content, Boolean isExecutable) throws EvalException; + + @SkylarkCallable( + name = "run", + doc = + "Creates an action that runs an executable. " + + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" + + "actions_run/execute.bzl\">See example of use</a>", + parameters = { + @Param( + name = "outputs", + type = SkylarkList.class, + generic1 = FileApi.class, + named = true, + positional = false, + doc = "List of the output files of the action." + ), + @Param( + name = "inputs", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = FileApi.class, + defaultValue = "[]", + named = true, + positional = false, + doc = "List or depset of the input files of the action." + ), + @Param( + name = "executable", + type = Object.class, + allowedTypes = { + @ParamType(type = FileApi.class), + @ParamType(type = String.class), + }, + named = true, + positional = false, + doc = "The executable file to be called by the action." + ), + @Param( + name = "tools", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = FileApi.class, + defaultValue = "unbound", + named = true, + positional = false, + doc = + "List or depset of any tools needed by the action. Tools are inputs with additional " + + "runfiles that are automatically made available to the action." + ), + @Param( + name = "arguments", + type = Object.class, + allowedTypes = { + @ParamType(type = SkylarkList.class), + }, + defaultValue = "[]", + named = true, + positional = false, + doc = + "Command line arguments of the action. " + + "Must be a list of strings or " + + "<a href=\"actions.html#args\"><code>actions.args()</code></a> objects." + ), + @Param( + name = "mnemonic", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "A one-word description of the action, for example, CppCompile or GoLink." + ), + @Param( + name = "progress_message", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Progress message to show to the user during the build, " + + "for example, \"Compiling foo.cc to create foo.o\"." + ), + @Param( + name = "use_default_shell_env", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = "Whether the action should use the built in shell environment or not." + ), + @Param( + name = "env", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "Sets the dictionary of environment variables." + ), + @Param( + name = "execution_requirements", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Information for scheduling the action. See " + + "<a href=\"$BE_ROOT/common-definitions.html#common.tags\">tags</a> " + + "for useful keys." + ), + @Param( + // TODO(bazel-team): The name here isn't accurate anymore. + // This is technically experimental, so folks shouldn't be too attached, + // but consider renaming to be more accurate/opaque. + name = "input_manifests", + type = SkylarkList.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "(Experimental) sets the input runfiles metadata; " + + "they are typically generated by resolve_command." + ) + }, + useLocation = true + ) + public void run( + SkylarkList outputs, + Object inputs, + Object executableUnchecked, + Object toolsUnchecked, + Object arguments, + Object mnemonicUnchecked, + Object progressMessage, + Boolean useDefaultShellEnv, + Object envUnchecked, + Object executionRequirementsUnchecked, + Object inputManifestsUnchecked, + Location location) + throws EvalException; + + @SkylarkCallable( + name = "run_shell", + doc = + "Creates an action that runs a shell command. " + + "<a href=\"https://github.com/bazelbuild/examples/tree/master/rules/" + + "shell_command/size.bzl\">See example of use</a>", + parameters = { + @Param( + name = "outputs", + type = SkylarkList.class, + generic1 = FileApi.class, + named = true, + positional = false, + doc = "List of the output files of the action." + ), + @Param( + name = "inputs", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = FileApi.class, + defaultValue = "[]", + named = true, + positional = false, + doc = "List or depset of the input files of the action." + ), + @Param( + name = "tools", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = FileApi.class, + defaultValue = "unbound", + named = true, + positional = false, + doc = + "List or depset of any tools needed by the action. Tools are inputs with additional " + + "runfiles that are automatically made available to the action." + ), + @Param( + name = "arguments", + allowedTypes = { + @ParamType(type = SkylarkList.class), + }, + defaultValue = "[]", + named = true, + positional = false, + doc = + "Command line arguments of the action. " + + "Must be a list of strings or " + + "<a href=\"actions.html#args\"><code>actions.args()</code></a> objects.<br>" + + "Blaze passes the elements in this attribute as arguments to the command." + + "The command can access these arguments as <code>$1</code>, <code>$2</code>, etc." + ), + @Param( + name = "mnemonic", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "A one-word description of the action, for example, CppCompile or GoLink." + ), + @Param( + name = "command", + type = Object.class, + allowedTypes = { + @ParamType(type = String.class), + @ParamType(type = SkylarkList.class, generic1 = String.class), + @ParamType(type = Runtime.NoneType.class), + }, + named = true, + positional = false, + doc = + "Shell command to execute.<br><br>" + + "<b>Passing a sequence of strings to this attribute is deprecated and Blaze may " + + "stop accepting such values in the future.</b><br><br>" + + "The command can access the elements of the <code>arguments</code> object via " + + "<code>$1</code>, <code>$2</code>, etc.<br>" + + "When this argument is a string, it must be a valid shell command. For example: " + + "\"<code>echo foo > $1</code>\". Blaze uses the same shell to execute the " + + "command as it does for genrules." + ), + @Param( + name = "progress_message", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Progress message to show to the user during the build, " + + "for example, \"Compiling foo.cc to create foo.o\"." + ), + @Param( + name = "use_default_shell_env", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = "Whether the action should use the built in shell environment or not." + ), + @Param( + name = "env", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "Sets the dictionary of environment variables." + ), + @Param( + name = "execution_requirements", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Information for scheduling the action. See " + + "<a href=\"$BE_ROOT/common-definitions.html#common.tags\">tags</a> " + + "for useful keys." + ), + @Param( + // TODO(bazel-team): The name here isn't accurate anymore. + // This is technically experimental, so folks shouldn't be too attached, + // but consider renaming to be more accurate/opaque. + name = "input_manifests", + type = SkylarkList.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "(Experimental) sets the input runfiles metadata; " + + "they are typically generated by resolve_command." + ) + }, + useLocation = true + ) + public void runShell( + SkylarkList outputs, + Object inputs, + Object toolsUnchecked, + Object arguments, + Object mnemonicUnchecked, + Object commandUnchecked, + Object progressMessage, + Boolean useDefaultShellEnv, + Object envUnchecked, + Object executionRequirementsUnchecked, + Object inputManifestsUnchecked, + Location location) + throws EvalException; + + @SkylarkCallable( + name = "expand_template", + doc = + "Creates a template expansion action. When the action is executed, it will " + + "generate a file based on a template. Parts of the template will be replaced " + + "using the <code>substitutions</code> dictionary. Whenever a key of the " + + "dictionary appears in the template, it is replaced with the associated value. " + + "There is no special syntax for the keys. You may, for example, use curly braces " + + "to avoid conflicts (for example, <code>{KEY}</code>). " + + "<a href=\"https://github.com/bazelbuild/examples/blob/master/rules/expand_template/hello.bzl\">" + + "See example of use</a>", + parameters = { + @Param( + name = "template", + type = FileApi.class, + named = true, + positional = false, + doc = "The template file, which is a UTF-8 encoded text file." + ), + @Param( + name = "output", + type = FileApi.class, + named = true, + positional = false, + doc = "The output file, which is a UTF-8 encoded text file." + ), + @Param( + name = "substitutions", + type = SkylarkDict.class, + named = true, + positional = false, + doc = "Substitutions to make when expanding the template." + ), + @Param( + name = "is_executable", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = "Whether the output file should be executable." + ) + } + ) + public void expandTemplate( + FileApi template, + FileApi output, + SkylarkDict<?, ?> substitutionsUnchecked, + Boolean executable) + throws EvalException; + + @SkylarkCallable( + name = "args", + doc = "Returns an Args object that can be used to build memory-efficient command lines.", + useEnvironment = true + ) + public CommandLineArgsApi args(Environment env); +} |