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 depset
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.
For this reason, the action-constructing functions accept Args
objects in addition to strings. Each Args
object represents a concatenation of strings and depsets, with optional transformations for manipulating the data. Args
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 Optimizing Performance page for more information.
Args
are constructed by calling ctx.actions.args()
. They can be passed as the arguments
parameter of ctx.actions.run()
or ctx.actions.run_shell()
. Each mutation of an Args
object appends values to the eventual command line.
The map_each
feature allows you to customize how items are transformed into strings. If you do not provide a map_each
function, the standard conversion is as follows:
- Values that are already strings are left as-is.
File
objects are turned into theirFile.path
values.Label
objects are turned into a string representation that resolves back to the same object when resolved in the context of the main repository. If possible, the string representation uses the apparent name of a repository in favor of the repository's canonical name, which makes this representation suited for use in BUILD files. While the exact form of the representation is not guaranteed, typical examples are//foo:bar
,@repo//foo:bar
and@@canonical_name~//foo:bar.bzl
.- All other types are turned into strings in an unspecified manner. For this reason, you should avoid passing values that are not of string or
File
type toadd()
, and if you pass them toadd_all()
oradd_joined()
then you should provide amap_each
function.
When using string formatting (format
, format_each
, and format_joined
params of the add*()
methods), the format template is interpreted in the same way as %
-substitution on strings, except that the template must have exactly one substitution placeholder and it must be %s
. Literal percents may be escaped as %%
. Formatting is applied after the value is converted to a string as per the above.
Each of the add*()
methods have an alternate form that accepts an extra positional parameter, an "arg name" string to insert before the rest of the arguments. For add_all
and add_joined
the extra string will not be added if the sequence turns out to be empty. For instance, the same usage can add either --foo val1 val2 val3 --bar
or just --bar
to the command line, depending on whether the given sequence contains val1..val3
or is empty.
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 use_param_file()
and set_param_file_format()
.
Example: Suppose we wanted to generate the command line:
--foo foo1.txt foo2.txt ... fooN.txt --bar bar1.txt,bar2.txt,...,barM.txt --baz
Args
object: # foo_deps and bar_deps are depsets containing # File objects for the foo and bar .txt files. args = ctx.actions.args() args.add_all("--foo", foo_deps) args.add_joined("--bar", bar_deps, join_with=",") args.add("--baz") ctx.actions.run( ... arguments = [args], ... )
Members
add
Args Args.add(arg_name_or_value, value=unbound, *, format=None)
Parameters
Parameter | Description |
---|---|
arg_name_or_value
|
required 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 value (see below).
|
value
|
default is unbound The object to append. It will be converted to a string using the standard conversion mentioned above. Since there is no map_each parameter for this function, value should be either a string or a File . A list, tuple, depset, or directory File must be passed to add_all() or add_joined() instead of this method.
|
format
|
string; or None ;
default is None A format string pattern, to be applied to the stringified version of value .
|
add_all
Args Args.add_all(arg_name_or_values, values=unbound, *, map_each=None, format_each=None, before_each=None, omit_if_empty=True, uniquify=False, expand_directories=True, terminate_with=None, allow_closure=False)
Most of the processing occurs over a list of arguments to be appended, as per the following steps:
- Each directory
File
item is replaced by allFile
s recursively contained in that directory. - If
map_each
is given, it is applied to each 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. - Each argument in the list is formatted with
format_each
, if present. - If
uniquify
is true, duplicate arguments are removed. The first occurrence is the one that remains. - If a
before_each
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. - Except in the case that the list is empty and
omit_if_empty
is true (the default), the arg name andterminate_with
are inserted as the first and last arguments, respectively, if they are given.
Parameters
Parameter | Description |
---|---|
arg_name_or_values
|
required If two positional parameters are passed this is interpreted as the arg name. The arg name is added before the values as a separate argument without any processing. This arg name will not be added if omit_if_empty is true (the default) and no other items are appended (as happens if values is empty or all of its items are filtered). If only one positional parameter is passed, it is interpreted as values (see below).
|
values
|
sequence; or depset;
default is unbound The list, tuple, or depset whose items will be appended. |
map_each
|
callable; or None ;
default is None 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. The function is passed either one or two positional arguments: the item to convert, followed by an optional The return value's type depends on how many arguments are to be produced for the item:
None 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.Ordinarily, items that are directories are automatically expanded to their contents when To avoid unintended retention of large analysis-phase data structures into the execution phase, the Warning: |
format_each
|
string; or None ;
default is None An optional format string pattern, applied to each string returned by the map_each function. The format string must have exactly one '%s' placeholder.
|
before_each
|
string; or None ;
default is None An optional argument to append before each argument derived from values is appended.
|
omit_if_empty
|
default is True If true, if there are no arguments derived from values to be appended, then all further processing is suppressed and the command line will be unchanged. If false, the arg name and terminate_with , if provided, will still be appended regardless of whether or not there are other arguments.
|
uniquify
|
default is False If true, duplicate arguments that are derived from values 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 map_each emits the same string for multiple items.
|
expand_directories
|
default is True If true, any directories in values will be expanded to a flat list of files. This happens before map_each is applied.
|
terminate_with
|
string; or None ;
default is None An optional argument to append after all other arguments. This argument will not be added if omit_if_empty is true (the default) and no other items are appended (as happens if values is empty or all of its items are filtered).
|
allow_closure
|
default is False If true, allows the use of closures in function parameters like map_each . Usually this isn't necessary and it risks retaining large analysis-phase data structures into the execution phase.
|
add_joined
Args Args.add_joined(arg_name_or_values, values=unbound, *, join_with, map_each=None, format_each=None, format_joined=None, omit_if_empty=True, uniquify=False, expand_directories=True, allow_closure=False)
Processing is similar to add_all()
, but the list of arguments derived from values
is combined into a single argument as if by join_with.join(...)
, and then formatted using the given format_joined
string template. Unlike add_all()
, there is no before_each
or terminate_with
parameter since these are not generally useful when the items are combined into a single argument.
If after filtering there are no strings to join into an argument, and if omit_if_empty
is true (the default), no processing is done. Otherwise if there are no strings to join but omit_if_empty
is false, the joined string will be an empty string.
Parameters
Parameter | Description |
---|---|
arg_name_or_values
|
required If two positional parameters are passed this is interpreted as the arg name. The arg name is added before values without any processing. This arg will not be added if omit_if_empty is true (the default) and there are no strings derived from values to join together (which can happen if values is empty or all of its items are filtered). If only one positional parameter is passed, it is interpreted as values (see below).
|
values
|
sequence; or depset;
default is unbound The list, tuple, or depset whose items will be joined. |
join_with
|
required A delimiter string used to join together the strings obtained from applying map_each and format_each , in the same manner as string.join() .
|
map_each
|
callable; or None ;
default is None Same as for add_all .
|
format_each
|
string; or None ;
default is None Same as for add_all .
|
format_joined
|
string; or None ;
default is None An optional format string pattern applied to the joined string. The format string must have exactly one '%s' placeholder. |
omit_if_empty
|
default is True If true, if there are no strings to join together (either because values 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).
|
uniquify
|
default is False Same as for add_all .
|
expand_directories
|
default is True Same as for add_all .
|
allow_closure
|
default is False Same as for add_all .
|
set_param_file_format
Args Args.set_param_file_format(format)
Parameters
Parameter | Description |
---|---|
format
|
required Must be one of:
The format defaults to "shell" if not called. |
use_param_file
Args Args.use_param_file(param_file_arg, *, use_always=False)
Bazel may choose to elide writing the params file to the output tree during execution for efficiency. If you are debugging actions and want to inspect the param file, pass --materialize_param_files
to your build.
Parameters
Parameter | Description |
---|---|
param_file_arg
|
required 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. For example, if the args are spilled to a params file "params.txt", then specifying "--file=%s" would cause the action command line to contain "--file=params.txt". |
use_always
|
default is False 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. |