一种操作经常需要一个大型命令行,其中包含从传递依赖项累积的值。例如,链接器命令行可以列出要链接的所有库所需的每个对象文件。最好将此类传递数据存储在 depset
中,以便多个目标共享它们。但是,如果规则作者必须将这些依赖项转换为字符串列表,才能构建操作命令行,则此内存共享优化会失败。
因此,操作构造函数除了接受字符串之外,还接受 Args
对象。每个 Args
对象表示一个字符串和依赖项的串联,其中包含用于操控数据的可选转换。在需要计算命令行的执行阶段之前,Args
对象不会处理它们封装的依赖项。这有助于将开销大的复制操作推迟到分析阶段完成之后。如需了解详情,请参阅优化性能页面。
Args
是通过调用 ctx.actions.args()
构造的。它们可以作为 ctx.actions.run()
或 ctx.actions.run_shell()
的 arguments
形参进行传递。Args
对象的每次更改都会将值附加到最终命令行。
借助 map_each
功能,您可以自定义项转换为字符串的方式。如果您未提供 map_each
函数,则标准转换如下所示:
- 已是字符串的值会保持不变。
File
对象会转换为其File.path
值。- 所有其他类型都将以未指定的方式转换为字符串。因此,您应避免将非字符串或
File
类型的值传递给add()
,如果将它们传递给add_all()
或add_joined()
,则应提供map_each
函数。
使用字符串格式设置(add*()
方法的 format
、format_each
和 format_joined
参数)时,格式模板的解释方式与字符串的 %
替换相同,不同之处在于模板必须有且仅有一个替换占位符,并且它必须是 %s
。字面量百分比可以转义为 %%
。按照上文所述,将值转换为字符串后,将应用格式。
每个 add*()
方法都有一个替代形式,该形式可接受额外的位置形参(即要在其余实参之前插入的“arg name”字符串)。对于 add_all
和 add_joined
,如果序列为空,将不会添加额外的字符串。例如,在相同的用法中,您可以向命令行添加 --foo val1 val2 val3 --bar
或仅添加 --bar
,具体取决于给定序列是包含 val1..val3
还是为空。
如果命令行的大小可以超过系统允许的大小上限,该参数可能会溢出到参数文件中。请参阅 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
|
required 如果传递了两个位置参数,则此参数会被解读为参数名称。参数名称会添加到值之前,而不进行任何处理。如果只传递了一个位置参数,则会被解读为 value (请参阅下文)。
|
value
|
default = unbound 要附加的对象。系统会通过上述标准转换将其转换为字符串。由于此函数没有 map_each 形参,因此 value 应为字符串或 File 。必须将列表、元组、depset 或目录 File 传递给 add_all() 或 add_joined() ,而不是此方法。
|
format
|
string; or None ;
default = 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(默认值),否则会分别将 arg name 和terminate_with
作为第一个参数和最后一个参数插入(如果提供的话)。
参数
参数 | 说明 |
---|---|
arg_name_or_values
|
required 如果传递了两个位置参数,则此参数会被解读为参数名称。参数名称会添加到 values 之前,不会进行任何处理。如果 omit_if_empty 为 true(默认值),并且未附加任何其他项(例如 values 为空或其所有项均经过过滤),则不会添加此参数名称。如果只传递了一个位置参数,则会被解读为 values (请参阅下文)。
|
values
|
sequence; or depset ;
default = unbound要附加其项的列表、元组或 depset。 |
map_each
|
callable; or None ;
default = None此函数可将每个项转换为零个或多个字符串,可以在附加之前进一步处理这些字符串。如果未提供此参数,系统会使用标准转化。 系统会向该函数传递一个或两个位置参数:要转换的项,后跟可选的 返回值的类型取决于要为项生成的参数数量:
None 与返回长度为 1 或长度为 0 的列表相同。不过,避免在不需要的地方创建列表更高效且更易读。通常,如果设置 为避免将大型分析阶段数据结构意外保留到执行阶段, 警告:调用 |
format_each
|
string; or None ;
default = None可选的格式字符串模式,适用于 map_each 函数返回的每个字符串。格式字符串必须正好有一个“%s”占位符。
|
before_each
|
string; or None ;
default = None要在附加每个派生自 values 的参数之前附加的可选字符串。
|
omit_if_empty
|
default = True 如果设为 true,如果没有派生自 values 的参数,则会禁止所有进一步处理,且命令行将保持不变。如果为 false,则无论是否存在其他参数,系统仍会附加参数名称和 terminate_with (如果提供)。
|
uniquify
|
default = False 如果为 true,将省略衍生自 values 的重复参数。系统只会保留每个参数在第一次出现时的日期。通常不需要此功能,因为依赖项已经省略了重复项,但如果 map_each 为多个项发出相同的字符串,则此功能非常有用。 |
expand_directories
|
default = True 如果为 true, values 中的任何目录都将展开为文件的扁平列表。这会在应用 map_each 之前发生。 |
terminate_with
|
string; or None ;
default = None要在所有其他参数后面附加的可选字符串。如果 omit_if_empty 为 true(默认值),并且未附加任何其他项(例如 values 为空或其所有项均经过过滤),则不会添加此字符串。
|
allow_closure
|
default = 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
|
required 如果传递了两个位置参数,则此参数会被解读为参数名称。参数名称会添加到 values 之前,不会进行任何处理。如果 omit_if_empty 为 true(默认值),并且没有从 values 派生的字符串可以联接在一起,则系统不会添加此参数(如果 values 为空或其所有项均经过过滤,就可能会发生这种情况)。如果只传递了一个位置参数,则会被解读为 values (请参阅下文)。
|
values
|
sequence; or depset ;
default = unbound要联接其项的列表、元组或 depset。 |
join_with
|
必需 一种分隔符字符串,用于将通过应用 map_each 和 format_each 获得的字符串组合在一起,采用与 string.join() 相同的方式。 |
map_each
|
callable; or None ;
default = None与 add_all 相同。
|
format_each
|
string; or None ;
default = None与 add_all 相同。
|
format_joined
|
string; or None ;
default = None应用于联接字符串的可选格式字符串模式。格式字符串必须正好有一个“%s”占位符。 |
omit_if_empty
|
default = True 如果为 true,如果没有要联接的字符串(因为 values 为空或其所有项均被滤除),则系统会禁止所有进一步的处理,并且命令行将保持不变。如果为 false,那么即使没有字符串可联接在一起,系统也会附加两个参数:arg 名称后跟一个空字符串(即零字符串的逻辑联接)。
|
uniquify
|
default = False 与 add_all 相同。
|
expand_directories
|
default = True 与 add_all 相同。
|
allow_closure
|
default = 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 文件中,则这些参数会被替换为包含此字符串的参数,且该字符串采用参数文件的路径。 例如,如果参数溢出到参数文件“params.txt”,则指定“--file=%s”会导致操作命令行包含“--file=params.txt”。 |
use_always
|
default = False 是否始终将参数溢出到参数文件。如果为 false,bazel 将根据您的系统和参数长度决定是否需要溢出参数。 |