「Make」變數是特殊類別的可展開字串變數,標示為「Subject to 'Make variant' substitution」的屬性可用於屬性。
這些物件可用於例如,將特定工具鍊路徑插入使用者建構的建構動作。
Bazel 會提供「預先定義的」變數和「自訂」變數;這些變數是在依附元件目標中定義,且僅供依附於這些變數的目標使用。
「Make」一詞是歷來原因:這些變數的語法和語意原本是為了與 GNU Make 比對相符。
使用
標示為 "Subject to 'Make variant' substitution" 的屬性可參照「Make」變數 FOO
,如下所示:
my_attr = "prefix $(FOO) suffix"
換句話說,任何符合 $(FOO)
的子字串都會展開為 FOO
的值。如果值為 "bar"
,最終字串會變成:
my_attr = "prefix bar suffix"
如果 FOO
不符合消耗目標的已知變數,Bazel 就會失敗並顯示錯誤。
「Make」變數的名稱為非字母符號 (例如 @
),也可只使用美元符號參照,而不用加上括號。例如:
my_attr = "prefix $@ suffix"
如要將 $
寫入為字串常值 (也就是為避免變數展開),請編寫 $$
。
預先定義的變數
任何目標中標示為「Subject to 'Make variant' substitution」的任何屬性都能參照預先定義的「Make」變數。
如要查看這些變數的清單和特定建構選項集的值,請執行
bazel info --show_make_env [build options]
然後查看最有大寫字母的輸出行。
工具鍊選項變數
COMPILATION_MODE
:fastbuild
、dbg
或opt
。(瞭解詳情)
路徑變數
-
BINDIR
:針對目標架構產生的二進位樹狀結構。請注意,在主機架構中執行的程式可能會使用不同的樹狀結構,以便支援跨平台程式碼編譯。
如果您想從
genrule
內執行工具,建議取得路徑為$(execpath toolname)
,其中 toolname 必須列於genrule
的tools
屬性中。 GENDIR
:針對目標架構產生的程式碼樹狀結構基礎。
機器架構變數
-
TARGET_CPU
:目標架構的 CPU,例如k8
。
預先定義的 Genrule 變數
以下內容特別適用於 genrule
的 cmd
屬性,在使該屬性正常運作的情況下,通常十分重要。
OUTS
:genrule
的outs
清單。如果只有一個輸出檔案,也可以使用$@
。-
SRCS
:genrule
的srcs
清單 (或更精確來說:與srcs
清單中標籤相對應的檔案路徑名稱)。如果只有一個來源檔案,則也可以使用$<
。 -
<
:SRCS
(如果是單一檔案)。否則會觸發建構錯誤。 -
@
:OUTS
(如果是單一檔案)。否則會觸發建構錯誤。 -
RULEDIR
:目標的輸出目錄,也就是與genfiles
或bin
樹狀結構下含有目標的套件名稱相對應的目錄。如果是//my/pkg:my_genrule
,即使//my/pkg:my_genrule
的輸出內容位於子目錄,也一律會以my/pkg
結尾。 -
@D
:輸出目錄。如果 outs 有一個項目,則會展開為包含該檔案的目錄。如果有多個項目,這會在genfiles
樹狀結構中展開為套件的根目錄,即使所有輸出檔案都位於同一個子目錄中!注意:請使用
RULEDIR
而非@D
,因為RULEDIR
的語意較簡單,且無論輸出檔案數量為何,行為都相同。如果 genrule 需要產生暫存中繼檔案 (或許是因為使用一些其他工具 (例如編譯器) 所致),則應嘗試將檔案寫入
@D
(雖然/tmp
也可以寫入),並在完成前將其移除。特別要避免寫入包含輸入內容的目錄。這些檔案可能位於唯讀檔案系統中。即使沒有執行這項操作,來源樹狀結構仍會移至垃圾桶。
預先定義的來源/輸出路徑變數
預先定義的變數 execpath
、execpaths
、rootpath
、rootpaths
、location
和 locations
會使用標籤參數 (例如 $(execpath
//foo:bar)
),並取代以該標籤表示的檔案路徑。
如果是來源檔案,這是與工作區根目錄的相對路徑。如果是規則的輸出檔案,這會是檔案的「輸出路徑」 (請參閱下方「輸出檔案」的說明)。
-
execpath
:代表 Bazel 執行建構動作的 execroot 底下的路徑。在上述範例中,Bazel 會在工作區根目錄中由
bazel-myproject
符號連結連結的目錄中執行所有建構動作。來源檔案empty.source
已在路徑bazel-myproject/testapp/empty.source
連結。因此,其執行路徑 (也就是根下方的子路徑) 為testapp/empty.source
。這是可用來尋找檔案的路徑建構動作。輸出檔案的結構類似,但輸出檔案的前置字串為
bazel-out/cpu-compilation_mode/bin
(或工具的輸出內容):bazel-out/cpu-opt-exec-hash/bin
。在上述範例中,//testapp:app
是工具,因為它會出現在show_app_output
的tools
屬性中。因此,其輸出檔案app
會寫入bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app
。因此 exec 路徑是bazel-out/cpu-opt-exec-hash/bin/testapp/app
。這個額外的前置字串可讓您建構相同的目標 (例如同一個建構中的兩個不同的 CPU),而不會互相衝突。傳送至這個變數的標籤只能代表一個檔案。對於代表來源檔案的標籤,此屬性會自動設為 true。如果是代表規則的標籤,規則只能產生一項輸出內容。如果這為 false 或標籤格式錯誤,建構作業就會失敗並產生錯誤。
-
rootpath
:代表已建構二進位檔在執行階段尋找依附元件時,可以使用的路徑是相對於主要存放區的執行檔案目錄子目錄。注意:只有在啟用--enable_runfiles
時才能使用這種做法,在 Windows 上並非預設情況。如需跨平台支援,請改用rlocationpath
。這與
execpath
類似,但會移除上述設定前置字串。在上述範例中,這表示empty.source
和app
都使用純工作區相關路徑:testapp/empty.source
和testapp/app
。外部存放區
repo
中檔案的rootpath
開頭是../repo/
,後面接著存放區相關路徑。這與
execpath
有相同的「僅限一項輸出」規定。 -
rlocationpath
:已建構二進位檔的路徑可以傳遞至執行檔案程式庫的Rlocation
函式,可在執行檔案目錄 (如有) 或使用執行檔案資訊清單尋找依附元件。這與
rootpath
類似,因為它不含設定前置字串,但不同之處在於它一律會以存放區名稱做為開頭。在上述範例中,這表示empty.source
和app
會產生下列路徑:myproject/testapp/empty.source
和myproject/testapp/app
。外部存放區
repo
中檔案的rlocationpath
開頭是repo/
,後面接著存放區相關路徑。如要在執行階段尋找依附元件,建議使用執行檔案程式庫,將此路徑傳遞至二進位檔,並使用執行檔案程式庫解析為檔案系統路徑。與
rootpath
相比,後者可以在所有平台上運作,甚至在沒有執行檔案目錄的情況下也能正常運作。這與
execpath
有相同的「僅限一項輸出」規定。 -
location
:execpath
或rootpath
的同義詞,視要展開的屬性而定。除非您確實瞭解特定規則的作用,否則這是舊版的 Starlark 行為,不建議使用。詳情請參閱 #2475。
execpaths
、rootpaths
、rlocationpaths
和 locations
是 execpath
、rootpath
、rlocationpaths
和 location
的複數形式。這類查詢支援產生多個輸出內容的標籤,在這種情況下,每項輸出內容會以空格分隔。零輸出規則和格式錯誤的標籤會產生建構錯誤。
所有參照的標籤都必須出現在消耗目標的 srcs
、輸出檔案或 deps
中。否則建構失敗。C++ 目標也可以參照 data
中的標籤。
標籤不一定要採用標準格式,例如 foo
、:foo
和 //somepkg:foo
皆可。
自訂變數
標示為「Subject to 'Make variant' substitution」的任何屬性皆可參照自訂「Make」變數,但這類變數僅限取決於定義這些變數的其他目標。
最佳做法是所有變數都應自訂,除非有充分理由將變數放入核心 Bazel 中。這樣 Bazel 就不必載入可能耗用大量資源的依附元件,進而提供使用 TAR 可能並不在乎的變數。
C++ 工具鍊變數
這是在 C++ 工具鍊規則中定義,適用於設定 toolchains =
["@bazel_tools//tools/cpp:current_cc_toolchain"]
部分規則 (例如 java_binary
) 的所有規則,會在規則定義中以隱含方式納入 C++ 工具鍊。這些變數會自動繼承這些變數。
內建 C++ 規則比「在其中執行編譯器」要複雜得多。為了支援各種編譯模式,例如 *SAN、ThinLTO、含/不含模組,以及仔細最佳化二進位檔,就像在多個平台快速執行測試時一樣,內建規則的用意也相當長,確保每個潛在多項內部產生的動作都設定正確的輸入內容、輸出內容和指令列旗標。
在極少數情況下,語言專家會使用這些變數做為備用機制。如果想要使用,請先與 Bazel 開發人員聯絡。
ABI
:C++ ABI 版本。-
AR
:Crosstool 的「ar」指令。 -
C_COMPILER
:C/C++ 編譯器 ID,例如llvm
。 -
CC
:C 和 C++ 編譯器指令。我們強烈建議您一律搭配使用
CC_FLAGS
和CC
。無法執行上述操作,您必須自行承擔相關風險。 CC_FLAGS
:一組最少的標記,讓 C/C++ 編譯器可透過 Genrules 使用。具體來說,如果CC
支援多個架構,這包含用來選取正確架構的旗標。-
NM
:Crosstool 的「nm」指令。 -
OBJCOPY
:來自與 C/C++ 編譯器相同套件的 objcopy 指令。 -
STRIP
:來自 C/C++ 編譯器相同套件的移除指令。
Java 工具鍊變數
以下是 Java 工具鍊規則中的定義,凡是設定 toolchains =
["@bazel_tools//tools/jdk:current_java_runtime"]
(或對應主機工具鍊對等項目的 "@bazel_tools//tools/jdk:current_host_java_runtime"
) 的規則都可以使用。
JDK 中的大部分工具不應直接使用。與上游工具相比,內建 Java 規則使用更複雜的 Java 編譯和封裝方法,例如介面 Jars、標頭介面 Jars,以及高度最佳化的 Jar 封裝和合併實作。
在極少數情況下,語言專家會使用這些變數做為備用機制。如果想要使用,請先與 Bazel 開發人員聯絡。
-
JAVA
:「java」指令 (Java 虛擬機器)。請避免這種情況,並盡可能使用java_binary
規則。可以是相對路徑。如果您在叫用java
前變更目錄,就必須先擷取工作目錄,才能變更目錄。 JAVABASE
:包含 Java 公用程式的基本目錄。可以是相對路徑。檔案會有一個「bin」子目錄。
Starlark 定義的變數
規則與工具鍊寫入者可以傳回 TemplateVariableInfo 提供者,以定義完全自訂變數。透過 toolchains
屬性依附於這些規則的任何規則,都可以讀取其值: