「Make」變數是可展開的字串變數特殊類別,可用於標示為「Subject to 'Make variable' substitution」的屬性。
例如,您可以使用這些路徑,將特定工具鍊路徑插入使用者建構的建構動作。
Bazel 提供預先定義變數,可供所有目標使用,也提供自訂變數,可在依附元件目標中定義,且僅供依附元件目標使用。
之所以使用「Make」一詞,是因為這個詞彙源自歷史:這些變數的語法和語意原本是為了與 GNU Make 相符。
使用
標示為「Subject to 'Make variable' substitution」的屬性可參照「Make」變數 FOO
,如下所示:
my_attr = "prefix $(FOO) suffix"
換句話說,任何與 $(FOO)
相符的子字串都會展開為 FOO
的值。如果該值為 "bar"
,最終字串會變成:
my_attr = "prefix bar suffix"
如果 FOO
不對應至使用目標所知的變數,Bazel 就會失敗並顯示錯誤。
名稱為非字母符號 (例如 @
) 的「Make」變數,也可以只使用貨幣符號進行參照,不必加上括號。例如:
my_attr = "prefix $@ suffix"
如要將 $
寫入為字串文字 (也就是避免變數展開),請寫入 $$
。
預先定義的變數
預先定義的「Make」變數可由任何目標上的任何屬性參照,且標示為「Subject to 'Make variable' substitution」。
如要查看這些變數的清單,以及特定建構選項的值,請執行
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
。Else 會觸發建構錯誤。 -
@
:如果是單一檔案,則為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
。因此,執行路徑為bazel-out/cpu-opt-exec-hash/bin/testapp/app
。這個額外的前置字串可讓您在同一個版本中為兩個不同的 CPU 建構相同的目標,而不會產生互相衝突的結果。傳遞至此變數的標籤必須代表單一檔案。對於代表來源檔案的標籤,這項屬性會自動設為 true。如果標籤代表規則,則規則必須產生一個輸出內容。如果為 False 或標籤格式錯誤,建構作業就會失敗並顯示錯誤訊息。
-
rootpath
:表示已建構的二進位檔可用於在執行階段找到依附元件的路徑,相對於對應主存放區的 runfiles 目錄子目錄。注意:這項功能必須啟用--enable_runfiles
才能運作,而 Windows 預設並未啟用這項功能。請改用rlocationpath
來支援跨平台。這與
execpath
類似,但會移除上述所述的設定前置字串。在上述範例中,這表示empty.source
和app
都使用純粹的相對工作區路徑:testapp/empty.source
和testapp/app
。外部存放區
repo
中檔案的rootpath
會以../repo/
開頭,後面接著存放區相對於路徑。這項要求與
execpath
的「僅限一個輸出項目」相同。 -
rlocationpath
:已建構的二進位檔路徑可傳遞至 runfiles 程式庫的Rlocation
函式,以便在執行階段找到依附元件,無論是在 runfiles 目錄 (如有) 中,或是使用 runfiles 資訊清單。這與
rootpath
相似,因為它不包含設定前置字串,但不同之處在於它一律以存放區名稱開頭。在上述範例中,這表示empty.source
和app
會產生以下路徑:myproject/testapp/empty.source
和myproject/testapp/app
。外部存放區
repo
中檔案的rlocationpath
會以repo/
開頭,後面接著存放區相對於路徑。將這個路徑傳遞至二進位檔,並使用 runfiles 程式庫將其解析為檔案系統路徑,是執行階段尋找依附元件的首選方法。與
rootpath
相比,這個方法的優點是可在所有平台上運作,即使無法使用 runfiles 目錄也沒問題。這項要求與
execpath
的「僅限一個輸出項目」相同。 -
location
:execpath
或rootpath
的同義詞,視展開的屬性而定。這是 Starlark 推出前的舊版行為,除非您確實知道這項行為對特定規則的影響,否則不建議使用。詳情請參閱 #2475。
execpaths
、rootpaths
、rlocationpaths
和 locations
分別是 execpath
、rootpath
、rlocationpaths
和 location
的複數變化版本。它們支援產生多個輸出的標籤,在這種情況下,每個輸出項目會以空格分隔列出。零輸出規則和格式錯誤的標籤會產生建構錯誤。
所有參照的標籤都必須出現在使用目標的 srcs
、輸出檔案或 deps
中。否則建構作業會失敗。C++ 目標也可以參照 data
中的標籤。
標籤不必採用標準格式:foo
、:foo
和 //somepkg:foo
都沒問題。
自訂變數
自訂「Make」變數可由任何標示為「Subject to 'Make variable' substitution」的屬性參照,但僅限於依賴定義這些變數的其他目標。
最佳做法是,除非有非常充分的理由將變數納入核心 Bazel,否則應自訂所有變數。這樣一來,Bazel 就不會需要載入可能耗費大量資源的依附元件,以便提供使用者可能不關心的變數。
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 編譯和封裝方法,例如介面 Jar、標頭介面 Jar 和經過高度最佳化的 Jar 封裝和合併實作。
這些變數是語言專家在少數情況下使用的備用機制。如果您想使用這些功能,請先與 Bazel 開發人員聯絡。
-
JAVA
:「java」指令 (Java 虛擬機器)。請避免這種情況,並盡可能改用java_binary
規則。可以是相對路徑。如果您必須先變更目錄,才能叫用java
,則必須先擷取工作目錄,再進行變更。 JAVABASE
:包含 Java 公用程式的基礎目錄。可以是相對路徑。其中會有「bin」子目錄。
Starlark 定義的變數
規則和工具鍊編寫者可以透過傳回 TemplateVariableInfo 供應器,定義完全自訂的變數。任何透過 toolchains
屬性依賴這些屬性的規則,都可以讀取這些值: