Args

回報問題 查看來源 Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

有時,動作會需要包含從遞移依附元件累積的值的大型指令列。舉例來說,連結器指令列可能會列出所有連結程式庫所需的所有物件檔案。最佳做法是將這類暫時性資料儲存在 depset 中,以便多個目標共用。不過,如果規則作者必須將這些 depsets 轉換為字串清單,才能建構動作指令列,就會破壞這項記憶體共用最佳化功能。

因此,動作建構函式除了字串外,也接受 Args 物件。每個 Args 物件都代表字串和 depsets 的串連,並可選擇性轉換來操控資料。Args 物件不會處理封裝的 depsets,直到執行階段要計算指令列時才會處理。這有助於延後任何昂貴的複製作業,直到分析階段完成為止。詳情請參閱「最佳化效能」頁面。

Args 是透過呼叫 ctx.actions.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*() 方法都有替代形式,可接受額外的位置參數,也就是要插入其餘引數之前的「arg name」字串。如果是 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。清單、元組、depsset 或目錄 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)

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

大部分的處理作業都是針對要附加的引數清單進行,步驟如下:

  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 必要
如果傳遞兩個位置參數,系統會將其解讀為引數名稱。arg 名稱會新增至 values 前方,做為獨立引數,且不會經過任何處理。如果 omit_if_empty 為 true (預設值) 且未附加其他項目 (如 values 為空或所有項目都經過篩選),系統就不會新增這個引數名稱。如果只傳遞一個位置參數,系統會將其解讀為 values (請參閱下文)。
values sequencedepset; 預設為 unbound
要附加項目的清單、元組或 depset。
map_each 可呼叫;或 None; 預設為 None
這個函式會將每個項目轉換為零或多個字串,這些字串可能會經過進一步處理,然後才附加。如未提供此參數,系統會使用標準轉換。

函式會傳遞一或兩個位置引數:要轉換的項目,以及選用的 DirectoryExpander。只有在提供的函式是使用者定義 (非內建) 且宣告多個參數時,才會傳遞第二個引數。

回傳值的型別取決於要為項目產生多少引數:

  • 在常見情況下,每個項目都會變成一個字串,因此函式應傳回該字串。
  • 如果想完全篩除項目,函式應傳回 None
  • 如果項目變成多個字串,函式會傳回這些字串的清單。
傳回單一字串或 None 的效果,分別等同於傳回長度為 1 或 0 的清單。不過,避免在不需要時建立清單,可提高效率和可讀性。

通常,如果設定 expand_directories=True,系統會自動展開目錄項目,顯示內容。不過,這不會展開其他值內含的目錄,例如項目是將目錄做為欄位的結構體。在這種情況下,您可以套用 DirectoryExpander 引數,手動取得特定目錄的檔案。

為避免在執行階段中意外保留大型分析階段資料結構,map_each 函式必須由頂層 def 陳述式宣告,預設不得為巢狀函式閉包。

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

format_each 字串;或 None; 預設為 None
選用的格式字串模式,會套用至 map_each 函式傳回的每個字串。格式字串只能有一個「%s」預留位置。
before_each 字串;或 None; 預設為 None
這是選用引數,可附加至從 values 衍生出的每個引數之前。
omit_if_empty bool; 預設值為 True
如果為 true,且沒有要附加的 values 衍生引數,系統就會停止所有後續處理作業,且命令列不會變更。如果設為 false,無論是否有其他引數,系統仍會附加引數名稱和 terminate_with (如有提供)。
uniquify bool; 預設值為 False
如果為 true,系統會省略衍生自 values 的重複引數。系統只會保留每個引數第一次出現的位置,通常不需要這項功能,因為 depsets 已省略重複項目,但如果 map_each 為多個項目發出相同字串,這項功能就很有用。
expand_directories bool; 預設為 True
如果為 true,values 中的所有目錄都會展開為扁平的檔案清單。這會在套用 map_each 前發生。
terminate_with 字串;或 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 sequencedepset; 預設為 unbound
要合併項目的清單、元組或 depset。
join_with string; 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 可呼叫項目;或 None; 預設值為 None
add_all 相同。
format_each 字串;或 None; 預設為 None
add_all 相同。
format_joined 字串;或 None; 預設為 None
套用至已聯結字串的選用格式字串模式。格式字串只能有一個「%s」預留位置。
omit_if_empty bool; 預設為 True
如果為 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; required
Must be one of:
  • 「multiline」:每個項目 (引數名稱或值) 都會逐字寫入參數檔案,並在後面加上換行字元。
  • 「shell」:與「multiline」相同,但項目會以殼層引號括住
  • 「flag_per_line」:與「multiline」相同,但 (1) 只有標記 (以「--」開頭) 會寫入參數檔案,且 (2) 標記的值 (如有) 會寫在同一行,並以「=」分隔符號分隔。這是 Abseil 旗標程式庫預期的格式。

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

use_param_file

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

將引數溢出至參數檔案,並以參數檔案的指標取代引數。如果 args 可能超出系統的指令長度限制,請使用此方法。

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

參數

參數 說明
param_file_arg 字串; 必要
含有單一「%s」的格式字串。如果引數溢出至參數檔案,系統會將引數替換為包含此字串的引數,並以參數檔案的路徑格式化。

舉例來說,如果 args 溢出至「params.txt」參數檔案,指定「--file=%s」會導致動作指令列包含「--file=params.txt」。

use_always bool; 預設值為 False
是否一律將引數溢出至參數檔案。如果為 false,Bazel 會根據系統和引數長度,決定是否需要溢出引數。