「Make」變數

「廠牌」變數是可展開字串變數的特殊類別,適用於標示為「必須加入「Make 變數」替換」的屬性。

舉例來說,這些屬性可用於在使用者建構的建構動作中插入特定工具鍊路徑。

Bazel 提供所有預先定義的變數 (所有目標皆可使用) 以及「自訂」變數。這些變數是在依附元件目標中定義,且僅適用於依賴這些變數的目標。

「Make」一詞的原因是歷史文物:這些變數的語法和語意最初旨在與 GNU Make 相符。

使用

標示為「受『Make 'Make 變數』替代』」的屬性可參照「Make」變數 FOO,如下所示:

my_attr = "prefix $(FOO) suffix"

也就是說,任何符合 $(FOO) 的子字串都會擴充為 FOO 的值。如果值為 "bar",則最終字串會變為:

my_attr = "prefix bar suffix"

如果 FOO 未對應至使用目標已知的變數,Bazel 就會執行失敗並顯示錯誤。

如果「Make」變數的名稱是非字母符號 (例如 @),也可以只使用錢幣符號進行參照,不使用括號。範例如下:

my_attr = "prefix $@ suffix"

如要將 $ 編寫為字串常值 (例如為了防止變數擴充),請寫入 $$

預先定義的變數

任何目標上標示為「必須加入「Make 變數」替代」的屬性,都可以參照預先定義的「Make」變數。

如要查看特定一組建構選項中的這些變數清單和變數值,請執行

bazel info --show_make_env [build options]

然後查看最上方的輸出行,當中含有大寫字母。

查看預先定義變數的範例

工具鍊選項變數

  • COMPILATION_MODEfastbuilddbgopt。(瞭解詳情)。

路徑變數

  • BINDIR:針對目標架構產生的二進位樹狀結構。

    請注意,在主機架構建構期間執行的程式,可能會使用不同的樹狀結構來支援跨平台編譯。

    如要從 genrule 中執行工具,取得路徑的建議方法是 $(execpath toolname),其中 toolname 必須列於 genruletools 屬性中。

  • GENDIR:針對目標架構產生的程式碼樹狀結構。

機器架構變數

  • TARGET_CPU:目標架構的 CPU,例如 k8

預先定義的 Genrule 變數

下列是 genrulecmd 屬性特別提供,對於使該屬性正常運作而言通常十分重要。

查看預先定義的 genrule 變數範例

  • OUTSgenruleouts 清單。如果只有一個輸出檔案,您也可以使用 $@
  • SRCSgenrulesrcs 清單 (更精確地說:與 srcs 清單中的標籤對應的檔案路徑名稱)。如果您只有一個來源檔案,也可以使用 $<
  • <SRCS (如果為單一檔案)。如未設定,就會觸發建構錯誤。
  • @OUTS (如果為單一檔案)。否則會觸發建構錯誤。
  • RULEDIR:目標的輸出目錄,也就是與 genfilesbin 樹狀結構下含有目標的套件名稱相對應的目錄。對於 //my/pkg:my_genrule,即使 //my/pkg:my_genrule 的輸出內容位於子目錄中,系統仍會一律以 my/pkg 結尾。

  • @D:輸出目錄。如果 outs 有一個項目,這個項目會展開為包含該檔案的目錄。如果有多個項目,此項目會展開為 genfiles 樹狀結構中的套件根目錄,即使所有輸出檔案都位於同一個子目錄中

    注意:請使用 RULEDIR 而非 @D,因為 RULEDIR 的語意較簡單,無論輸出檔案數量為何,運作方式都相同。

    如果 Genrule 需要產生臨時中繼檔案 (可能是使用編譯器等其他工具的結果),則應嘗試將其寫入 @D (雖然 /tmp 也會寫入),並在完成前移除。

    尤其避免寫入包含輸入內容的目錄。這些檔案可能位於唯讀檔案系統上。即使並未這麼做,這樣做仍會刪除來源樹狀結構。

預先定義的來源/輸出路徑變數

預先定義的變數 execpathexecpathsrootpathrootpathslocationlocations 會使用標籤參數 (例如 $(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_outputtools 屬性中。因此,其輸出檔案 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:表示建構的二進位檔可在執行階段尋找依附元件 (相對於其與主要存放區對應之執行檔目錄的子目錄) 的路徑。注意:只有在已啟用 --enable_runfiles (在 Windows 上預設未啟用的情況下) 時,這個選項才能正常運作。如需跨平台支援,請改用 rlocationpath

    execpath 類似,但會移除上述的設定前置字串。在上述範例中,這表示 empty.sourceapp 都使用純工作區相關路徑:testapp/empty.sourcetestapp/app

    外部存放區 repo 中檔案的 rootpath 開頭是 ../repo/,後面接著存放區相對路徑。

    這和 execpath 的「僅限輸出」要求相同。

  • rlocationpath:建構二進位檔可傳送至 runfile 程式庫的 Rlocation 函式的路徑,以便在執行階段尋找依附元件,位置位於 runfile 目錄 (如有) 中,或使用執行檔案資訊清單。

    這與 rootpath 類似,它不包含設定前置字串,但差別在於一律以存放區名稱開頭。在上述範例中,這表示 empty.sourceapp 會產生以下路徑:myproject/testapp/empty.source myproject/testapp/app

    外部存放區 repo 中檔案的 rlocationpath 開頭是 repo/,後面接著存放區相對路徑。

    如要在執行階段找出依附元件,建議您將這個路徑傳送至二進位檔,並使用執行檔案程式庫解析為檔案系統路徑。與 rootpath 相比,它可支援所有平台,即使無法使用 runfile 目錄,也有優勢。

    這和 execpath 的「僅限輸出」要求相同。

  • locationexecpathrootpath 的同義詞,視展開的屬性而定。這是舊版 Starlark 應用程式行為,除非您非常瞭解特定規則的用途,否則不建議採用。詳情請參閱 #2475

execpathsrootpathsrlocationpathslocationsexecpathrootpathrlocationpathslocation 的複數變化版本。協同程式支援產生多個輸出內容的標籤,在這種情況下,系統會用空格分隔每個輸出內容。零輸出規則和格式錯誤的標籤會產生建構錯誤。

所有參照的標籤都必須出現在所用目標的 srcs、輸出檔案或 deps 中。否則建構會失敗C++ 目標也可以參照 data 中的標籤。

標籤不一定要使用標準格式:foo:foo//somepkg:foo

自訂變數

任何標示為「取決於『Make 變數』替代性」的屬性,都可以參照自訂「Make」變數,但前提是目標必須仰賴「定義」這些變數的其他目標。

最佳做法是,所有變數都應自訂,除非有充分理由將變數納入核心 Bazel。如此一來,Bazel 就不用載入可能昂貴的依附元件,以便供應消耗的變數。

C++ 工具鍊變數

以下內容在 C++ 工具鍊規則中定義,適用於設定 toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] (或對應主機工具鍊相等內容的任何規則) 適用的 "@bazel_tools//tools/cpp:current_cc_host_toolchain"。某些規則 (例如 java_binary) 會以隱含方式在規則定義中加入 C++ 工具鍊。這些變數會自動繼承這些變數。

內建 C++ 規則比「在其上執行編譯器」更為複雜。為了支援 *SAN、TinLTO (包含/不含模組) 等多樣化的編譯模式,以及搭配/不含模組的快速最佳化二進位檔,以及在多個平台上快速執行測試時,內建規則可以達到絕佳的長度,以確保每個可能由多個內部產生的動作都能設定正確的輸入內容、輸出內容和指令列旗標。

這些變數是語言專家在極少數情況下使用的備用機制。如果您想使用這些功能,請先與 Bazel 開發人員聯絡

  • ABI:C++ ABI 版本。
  • AR: Crosstool 的「ar」指令。
  • C_COMPILER:C/C++ 編譯器 ID,例如 llvm
  • CC:C 和 C++ 編譯器指令。

    強烈建議您一律將 CC_FLAGSCC 搭配使用。無法自行承擔風險。

  • 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、標頭介面 Jar,以及高度最佳化的 Jar 封裝和合併實作。

這些變數是語言專家在極少數情況下使用的備用機制。如果您想使用這些功能,請先與 Bazel 開發人員聯絡

  • JAVA:「java」指令 (Java 虛擬機器)。請避免這種情況,並盡可能使用 java_binary 規則。可以是相對路徑。如果必須在叫用 java 前變更目錄,則必須先擷取工作目錄才能變更目錄。
  • JAVABASE:包含 Java 公用程式的基本目錄。可以是相對路徑。叢集上有「bin」子目錄。

Starlark 定義的變數

規則和工具鍊寫入者可以傳回 TemplateVariableInfo 提供者,藉此定義完全自訂變數。任何透過 toolchains 屬性仰賴的規則都可以讀取其值:

查看 Starlark 定義變數的範例