Args

回報問題 查看來源 Nightly

以節省記憶體的方式封裝物件,建構部分或所有指令列所需的資料。

通常會發生動作需要大型指令列,其中含有從遞移依附元件累積的值。例如,連結器指令列可能會列出所有連結程式庫所需的每個物件檔案。最佳做法是將這類遞移資料儲存在 depset 中,以便多個目標共用。不過,如果規則作者必須將這些解碼集轉換為字串清單,才能建構動作指令列,就會使這項記憶體共用最佳化作業失效。

因此,除了字串外,動作建構函式也接受 Args 物件。每個 Args 物件都代表字串與解碼集的串連,並可選擇用於操控資料的選用轉換。在計算指令列時,Args 物件不會處理其封裝到執行階段之前封裝的 DepSet。這有助於將任何昂貴的複製作業延後,直到分析階段結束為止。詳情請參閱最佳化成效頁面。

呼叫 ctx.actions.args() 即可建構 Args。可做為 ctx.actions.run()ctx.actions.run_shell()arguments 參數傳遞。每項 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 函式。

使用字串格式 (add*() 方法的 formatformat_eachformat_joined 參數) 時,格式範本的解讀方式與字串上的 % 替代方式相同,但範本只能有一個替換預留位置,且必須為 %s。常值百分比可以逸出為 %%。系統會依照上述方法,在值轉換為字串後套用格式設定。

每個 add*() 方法都有替代形式,可接受額外的位置參數,即要在引數其餘部分之前插入的「引數名稱」字串。針對 add_alladd_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 string;或 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)

將多個引數附加至這個指令列。系統會在執行階段延遲處理這些項目。

處理程序大多會透過附加的引數清單進行,如以下步驟所示:

  1. 每個目錄的 File 項目都會由該目錄以遞迴方式納入的所有 File 取代。
  2. 如果指定 map_each,就會套用至每個項目,而產生的字串清單會串連起來,以形成初始引數清單。否則,初始引數清單是為每個項目套用標準轉換的結果。
  3. 清單中的每個引數都會採用 format_each 的格式 (如果有的話)。
  4. 如果 uniquify 為 true,則會移除重複的引數。第一種是剩下的
  5. 如果指定了 before_each 字串,系統會將該字串以新引數的形式插入清單中的每個現有引數。這會有效使這個點附加的引數數量增加了一倍。
  6. 除了清單為空白且 omit_if_empty 為 true (預設值) 的情況下,系統會在有指定引數時,分別插入引數名稱和 terminate_with 做為第一個和最後一個引數。
請注意,空白字串是需要執行所有處理步驟的有效引數。

參數

參數 說明
arg_name_or_values 必要
如果傳遞兩個位置參數,系統會將其解讀為引數名稱。引數名稱會在 values 之前新增為單獨的引數,且未進行任何處理。如果 omit_if_empty 為 true (預設值),且未附加其他項目 (也就是 values 空白或所有項目都遭到篩除),系統就不會新增這個引數名稱。如果只傳遞一個位置參數,系統會將其視為 values (詳見下文)。
values sequence;或 depset;預設值為 unbound
要附加其項目的清單、元組或解碼集。
map_each 可呼叫;或 None;預設值為 None
此函式可將各個項目轉換為零或多個字串,這些項目可能會在附加前進一步處理。如未提供這個參數,系統會使用標準轉換。

系統會傳送一或兩個位置引數:要轉換的項目,後面加上選用的 DirectoryExpander。只有在提供的函式為使用者定義 (非內建) 並宣告多個參數時,系統才會傳遞第二個引數。

傳回值的類型取決於需要為項目產生的引數數量:

  • 常見情況下,當每個項目變成一個字串時,函式應傳回該字串。
  • 如果要完全篩除項目,函式應傳回 None
  • 如果該項目變成多個字串,函式就會傳回這些字串的清單。
傳回單一字串或 None,效果等同於傳回長度為 1 或長度 0 的清單。不過,這種做法會更有效率且易於閱讀,避免在非必要的情況下建立清單。

一般來說,如果設定了 expand_directories=True,屬於目錄的項目會自動展開至其內容。不過,這樣不會展開其他值內包含的目錄;例如,當項目是具有目錄做為欄位的 struct 時。在這種情況下,可以套用 DirectoryExpander 引數,手動取得指定目錄的檔案。

為避免在執行階段中意外保留大型分析階段資料結構,您必須透過頂層 def 陳述式宣告 map_each 函式,該函式可能不會預設關閉。

警告:在呼叫 map_each 期間執行的 print() 陳述式不會產生任何可見的輸出內容。

format_each string; 或 None;預設值為 None
選用的格式字串模式,會套用至 map_each 函式傳回的每個字串。格式字串只能有一個「%s」預留位置。
before_each string;或 None;預設值為 None
在每個衍生自 values 的引數之前,要附加的選用引數。
omit_if_empty bool;預設值為 True
如果設為 true,沒有附加 values 的引數,則所有後續處理作業均抑制,且指令列不會變更。如果是 False,則無論是否有其他引數,仍會附加引數名稱和 terminate_with (如有)。
uniquify bool;預設值為 False
如果設為 true,系統會省略衍生自 values 的重複引數。系統只會保留每個引數的第一個出現引數。由於解碼集已經省略重複內容,因此通常不需要這項功能,但如果 map_each 對多個項目發出同一個字串,將能派上用場。
expand_directories bool;預設值為 True
如果設為 true,values 中的任何目錄都會展開為平面檔案清單。這項作業會在套用 map_each 前執行。
terminate_with string; 或 None;預設為 None
要附加在所有引數之後的選用引數。如果 omit_if_empty 為 true (預設值),且未附加其他項目,就不會新增這個引數 (例如 values 空白或所有項目都遭到篩除)。
allow_closure bool;預設值為 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_eachterminate_with 參數。

篩選之後,如果沒有可聯結到引數的字串,且 omit_if_empty 為 true (預設值),則系統不會處理任何處理作業。如果沒有要彙整的字串,但 omit_if_empty 為 false,則聯結字串將會是空字串。

參數

參數 說明
arg_name_or_values 必要
如果傳遞兩個位置參數,系統會將其解讀為引數名稱。引數名稱是在 values 之前新增,沒有任何處理。如果 omit_if_empty 為 true (預設值),且沒有從 values 彙整的任何字串 (如果 values 為空白或所有項目都遭到篩除,系統就不會新增此引數)。如果只傳遞一個位置參數,系統會將其視為 values (詳見下文)。
values sequence;或 depset;預設為 unbound
其項目會彙整的清單、元組或 depset。
join_with string;必要
用於彙整套用 map_eachformat_each 所取得字串的分隔符號,與 string.join() 相同。
map_each callable; 或 None; 預設值為 None
add_all 相同。
format_each string;或 None;預設值為 None
add_all 相同。
format_joined string; 或 None;預設值為 None
這是套用至已彙整字串的選用格式字串模式。格式字串只能有一個「%s」預留位置。
omit_if_empty bool;預設值為 True
如果沒有一起彙整的字串 (因為 values 為空白或其中所有項目都經過篩選),則系統會抑制所有後續處理作業,且指令列不會改變。如果設為 False,則即使沒有可彙整的字串,仍會加上兩個引數:引數名稱後接空字串 (零字串的邏輯彙整)。
uniquify bool;預設值為 False
add_all 相同。
expand_directories bool;預設值為 True
add_all 相同。
allow_closure bool;預設值為 False
add_all 相同。

set_param_file_format

Args Args.set_param_file_format(format)

設定參數檔案的格式 (如有使用)

參數

參數 說明
format string;必要
必須是下列其中一個值:
  • 「多行」:每個項目 (引數名稱或值) 都會完整寫入參數檔案,並在後方加上換行字元。
  • "shell": 與「multiline」相同,但項目會加上 Shell 引號
  • 「flag_per_line」:與「multiline」相同,但 (1) 只有標記 (以「--」開頭) 寫入參數檔案;以及 (2) 標記的值 (如果有的話) 會在同一行寫入「=」分隔符。這是 Abseil 旗標程式庫預期的格式。

如未呼叫,格式會預設為「shell」。

use_param_file

Args Args.use_param_file(param_file_arg, *, use_always=False)

將引數填入參數檔案,並替換為參數檔案的指標。當引數可能超過系統指令長度限制時,請使用 。

Bazel 可能會選擇盡量減少在執行期間將參數檔案寫入輸出樹狀結構,藉此提高效率。如果您要對動作進行偵錯,並想檢查參數檔案,請將 --materialize_param_files 傳遞至建構作業。

參數

參數 說明
param_file_arg string;必要
包含單個「%s」的格式字串。如果引數溢出至參數檔案,系統會將引數替換成由這個字串 (採用參數檔案路徑格式) 組成的引數。

舉例來說,如果引數會放在參數檔案「params.txt」,那麼指定「--file=%s」就會造成動作指令列包含「--file=params.txt」。

use_always bool;預設值為 False
。是否一律將引數張貼到參數檔案。設為 false 時,bazel 會根據系統和引數長度決定是否需要將引數排出。