通常,某项操作需要一个包含从传递依赖项累积的值的大型命令行。例如,链接器命令行可能会列出所有被链接的库所需的所有对象文件。最佳做法是将此类传递数据存储在 depset 中,以便多个目标可以共享这些数据。但是,如果规则作者必须将这些 depset 转换为字符串列表才能构建操作命令行,那么这种内存共享优化就会失效。
因此,操作构建函数除了接受字符串之外,还接受 Args 对象。每个 Args 对象都表示字符串和 depset 的串联,并提供用于操纵数据的可选转换。Args 对象不会处理它们封装的 depset,直到执行阶段需要计算命令行时才会处理。这有助于将任何开销较大的复制操作延迟到分析阶段完成后进行。如需了解详情,请参阅优化性能页面。
Args 通过调用 ctx.actions.args() 构建。它们可以作为 arguments 参数传递给 ctx.actions.run() 或 ctx.actions.run_shell()。对 Args 对象的每次突变都会将值附加到最终的命令行。
借助 map_each 功能,您可以自定义项转换为字符串的方式。如果您未提供 map_each 函数,则标准转换如下所示:
- 已是字符串的值将保持不变。
File对象将转换为其File.path值。Label对象将转换为字符串表示形式,该表示形式在主代码库的上下文中解析时会解析回同一对象。如果可能,字符串表示形式会使用代码库的显示名称,而不是代码库的规范名称,这使得此表示形式适合在 BUILD 文件中使用。虽然无法保证表示形式的确切形式,但典型示例包括//foo:bar、@repo//foo:bar和@@canonical_name~//foo:bar.bzl。- 所有其他类型都以未指定的方式转换为字符串。因此,您应避免将非字符串或
File类型的值传递给add(),如果您将这些值传递给add_all()或add_joined(),则应提供map_each函数。
使用字符串格式设置(format、format_each 和 format_joined 方法的 add*() 参数)时,格式模板的解读方式与字符串的 % 替换相同,但模板必须只有一个替换占位符,并且必须是 %s。字面百分号可以转义为 %%。格式设置会在值按照上述方式转换为字符串后应用。
每个 add*() 方法都有一个替代形式,该形式接受一个额外的位置参数,即在其余参数之前插入的“arg name”字符串。对于 add_all 和 add_joined,如果序列为空,则不会添加额外的字符串。例如,根据给定序列是否包含 val1..val3 或是否为空,同一用法可以向命令行添加 --foo val1 val2 val3 --bar 或仅添加 --bar。
如果命令行的大小可能会超过系统允许的最大大小,则可以将参数溢出到参数文件中。请参阅 use_param_file() 和 set_param_file_format()。
示例:假设我们要生成以下命令行:
--foo foo1.txt foo2.txt ... fooN.txt --bar bar1.txt,bar2.txt,...,barM.txt --baz
Args 对象:
# 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],
...
)
成员
add
Args Args.add(arg_name_or_value, value=unbound, *, format=None)
参数
| 参数 | 说明 |
|---|---|
arg_name_or_value
|
必需 如果传递了两个位置参数,则此参数将被解读为实参名称。实参名称将在值之前添加,而无需进行任何处理。如果仅传递了一个位置参数,则该参数将被解读为 value(见下文)。
|
value
|
默认值为 unbound要附加的对象。它将使用上述标准转换转换为字符串。由于此函数没有 map_each 参数,因此 value 应为字符串或 File。列表、元组、depset 或目录 File 必须传递给 add_all() 或 add_joined(),而不是此方法。
|
format
|
字符串;或 None;
默认值为 None一个格式字符串模式,将应用于 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)
大多数处理都是针对要附加的实参列表进行的,具体步骤如下:
- 每个目录
File项都将替换为该目录中以递归方式包含的所有File。 - 如果给定了
map_each,则它将应用于每个项,并且生成的字符串列表将串联起来以形成初始实参列表。否则,初始实参列表就是将标准转换应用于每个项的结果。 - 列表中的每个实参都将使用
format_each(如果存在)进行格式设置。 - 如果
uniquify为 true,则会移除重复的实参。第一个出现的实参将保留。 - 如果给定了
before_each字符串,则它将作为新实参插入到列表中每个现有实参之前。这实际上使要附加的实参数量增加了一倍。 - 除非列表为空且
omit_if_empty为 true(默认值),否则实参名称和terminate_with将分别作为第一个和最后一个实参插入(如果给定)。 请注意,空字符串是有效的实参,需要遵循所有这些处理步骤。
参数
| 参数 | 说明 |
|---|---|
arg_name_or_values
|
必需 如果传递了两个位置参数,则此参数将被解读为实参名称。实参名称将在 values 之前添加,作为单独的实参,而无需进行任何处理。如果 omit_if_empty 为 true(默认值)且未附加其他项(如果 values 为空或其所有项都被过滤掉,则会发生这种情况),则不会添加此实参名称。如果仅传递了一个位置参数,则该参数将被解读为 values(见下文)。
|
values
|
序列;或 depset;
默认值为 unbound将附加其项的列表、元组或 depset。 |
map_each
|
可调用对象;或 None;
默认值为 None一个函数,用于将每个项转换为零个或多个字符串,这些字符串可能会在附加之前进行进一步处理。如果未提供此参数,则使用标准转换。 该函数将传递一个或两个位置参数:要转换的项,后跟可选的 返回值的类型取决于要为该项生成的实参数量:
None 的效果与分别返回长度为 1 或长度为 0 的列表相同。但是,避免在不需要时创建列表会更高效且更易读。通常,当设置 为避免在执行阶段意外保留分析阶段的大型数据结构, 警告: |
format_each
|
字符串;或 None;
默认值为 None一个可选的格式字符串模式,应用于 map_each 函数返回的每个字符串。格式字符串必须只有一个“%s”占位符。
|
before_each
|
字符串;或 None;
默认值为 None一个可选实参,用于在附加从 values 派生的每个实参之前附加。
|
omit_if_empty
|
默认值为 True如果为 true,则表示如果没有从 values 派生的实参要附加,则会禁止所有进一步的处理,并且命令行将保持不变。如果为 false,则无论是否有其他实参,实参名称和 terminate_with(如果提供)仍将附加。
|
uniquify
|
默认值为 False如果为 true,则会省略从 values 派生的重复实参。每个实参只会保留第一个出现的位置。通常不需要此功能,因为 depset 已经省略了重复项,但如果 map_each 为多个项发出相同的字符串,则此功能可能会很有用。
|
expand_directories
|
默认值为 True如果为 true,则 values 中的任何目录都将展开为文件的扁平列表。这会在应用 map_each 之前发生。
|
terminate_with
|
字符串;或 None;
默认值为 None一个可选实参,用于在所有其他实参之后附加。如果 omit_if_empty 为 true(默认值)且未附加其他项(如果 values 为空或其所有项都被过滤掉,则会发生这种情况),则不会添加此实参。
|
allow_closure
|
默认值为 False如果为 true,则允许在函数参数(如 map_each)中使用闭包。通常,这没有必要,并且可能会在执行阶段保留分析阶段的大型数据结构。
|
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)
处理方式与 add_all() 类似,但从 values 派生的实参列表会合并为一个实参,就像使用 join_with.join(...) 一样,然后使用给定的 format_joined 字符串模板进行格式设置。与 add_all() 不同,没有 before_each 或 terminate_with 参数,因为当项合并为一个实参时,这些参数通常没有用。
如果在过滤后没有要串联到实参中的字符串,并且 omit_if_empty 为 true(默认值),则不会进行任何处理。否则,如果没有要串联的字符串但 omit_if_empty 为 false,则串联的字符串将为空字符串。
参数
| 参数 | 说明 |
|---|---|
arg_name_or_values
|
必需 如果传递了两个位置参数,则此参数将被解读为实参名称。实参名称将在 values 之前添加,而无需进行任何处理。如果 omit_if_empty 为 true(默认值)且没有从 values 派生的字符串要串联在一起(如果 values 为空或其所有项都被过滤掉,则会发生这种情况),则不会添加此实参。如果仅传递了一个位置参数,则该参数将被解读为 values(见下文)。
|
values
|
序列;或 depset;
默认值为 unbound将串联其项的列表、元组或 depset。 |
join_with
|
必需 一个分隔符字符串,用于以与 string.join() 相同的方式将通过应用 map_each 和 format_each 获得的字符串串联在一起。
|
map_each
|
可调用对象;或 None;
默认值为 None与 add_all 相同。
|
format_each
|
字符串;或 None;
默认值为 None与 add_all 相同。
|
format_joined
|
字符串;或 None;
默认值为 None一个可选的格式字符串模式,应用于串联的字符串。格式字符串必须只有一个“%s”占位符。 |
omit_if_empty
|
默认值为 True如果为 true,则表示如果没有要串联在一起的字符串(因为 values 为空或其所有项都被过滤掉),则会禁止所有进一步的处理,并且命令行将保持不变。如果为 false,则即使没有要串联在一起的字符串,也会附加两个实参:实参名称后跟一个空字符串(这是零个字符串的逻辑串联)。
|
uniquify
|
默认值为 False与 add_all 相同。
|
expand_directories
|
默认值为 True与 add_all 相同。
|
allow_closure
|
默认值为 False与 add_all 相同。
|
set_param_file_format
Args Args.set_param_file_format(format)
参数
| 参数 | 说明 |
|---|---|
format
|
必需 必须是以下其中一项:
如果未调用,则格式默认为“shell”。 |
use_param_file
Args Args.use_param_file(param_file_arg, *, use_always=False)
Bazel 可能会选择在执行期间省略将参数文件写入输出树,以提高效率。如果您要调试操作并检查参数文件,请将 --materialize_param_files 传递给您的 build。
参数
| 参数 | 说明 |
|---|---|
param_file_arg
|
必需 一个格式字符串,其中包含一个“%s”。如果实参溢出到参数文件中,则它们将被替换为一个实参,该实参由使用参数文件的路径设置格式的此字符串组成。 例如,如果实参溢出到参数文件“params.txt”,则指定“--file=%s”会导致操作命令行包含“--file=params.txt”。 |
use_always
|
默认值为 False是否始终将实参溢出到参数文件中。如果为 false,bazel 将根据您的系统和实参长度决定是否需要溢出实参。 |