「製作」變數」

回報問題 查看原始碼

「Make」變數是特殊類別的可展開字串變數,適用於標示為「Make ‘'makevariable' substitution"」的屬性。

舉例來說,您可以使用這些方法將特定工具鍊路徑插入使用者建構的建構動作。

Bazel 提供所有預先定義的目標都適用的預先定義變數,以及可在依附元件目標中定義的 custom 變數,且僅適用於需要這些變數的目標。

「Make」一詞的歷史為歷史,這些變數的語法和語意原本就要比對出 GNU Make

使用

標示為 "Subject to 'Make var' substitution" 的屬性可參照「Make」變數 FOO,如下所示:

my_attr = "prefix $(FOO) suffix"

換句話說,凡是符合 $(FOO) 的子字串,都會擴展為 FOO 的值。如果該值為 "bar",最終字串就會變成:

my_attr = "prefix bar suffix"

如果 FOO 未對應至消耗目標的已知變數,Bazel 就會發生錯誤並失敗。

您也可以使用名稱中的非字母符號 (例如 @) 來參照「Make」變數,也可以使用括號符號來參照 (不含括號)。範例如下:

my_attr = "prefix $@ suffix"

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

預先定義的變數

任何目標上的任何屬性都會標示為「以『變數』替代變數」,藉此參照預先定義的「Make」變數。

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

bazel info --show_make_env [build options]

查看大寫的書寫行。

查看預先定義變數的範例

工具鍊選項變數

  • COMPILATION_MODEfastbuilddbgopt。(瞭解詳情)

路徑變數

  • BINDIR:為目標架構產生的二進位樹狀結構的底數。

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

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

  • GENDIR:為目標架構產生的程式碼樹狀結構的底數。

機器架構變數

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

預先定義的產生器規則

下列是 genrulecmd 屬性的特別項目,通常對這項屬性來說至關重要。

查看預先定義的產生器規則範例

  • 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 執行 Bazel 執行建構動作時的路徑。

    在上述範例中,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)。因此,其輸出檔案 app 會寫入 bazel-myproject/bazel-out/cpu-opt-exec-hash/bin/testapp/app。因此執行路徑為 bazel-out/cpu-opt-exec-hash/bin/testapp/app。有了這個額外的前置字串,您就能在同一個版本中為兩個不同的 CPU 建構相同的目標,而不會互相覆蓋。

    傳送至這個變數的標籤必須代表一個檔案。對於代表來源檔案的標籤,系統會自動套用這項設定。對於代表規則的標籤,規則必須產生一個輸出。如果為 False 或標籤格式錯誤,建構作業就會發生錯誤並發生錯誤。

  • rootpath:代表已建構二進位檔的對應路徑,可在執行階段中根據其與主要存放區的執行檔案目錄相對地尋找依附元件。 注意:只有在 --enable_runfiles 已啟用的情況下,此設定才適用於 Windows 系統。如需跨平台支援,請改用 rlocationpath

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

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

    這與 execpath 具有相同的「僅限輸出」需求。

  • rlocationpath:已建構的二進位檔可以傳遞至 Runfile 程式庫的 Rlocation 函式,藉此在執行階段找出依附元件。您可以在 runfiles 目錄 (如果有) 或使用 runfiles 資訊清單,以找出依附元件。

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

    外部存放區 repo 中的檔案 rlocationpathrepo/ 開頭,後接存放區存放區的路徑。

    如要將這個路徑傳送至二進位檔,並使用 Runfile 程式庫將其解析至檔案系統路徑,建議您在執行階段找出依附元件。與 rootpath 相比,它可以在所有平台上正常運作,即使沒有執行 runfile 目錄也能受益。

    這與 execpath 具有相同的「僅限輸出」需求。

  • locationexecpathrootpath 的同義詞 (視展開的屬性而定)。這是舊版的 Starstark 舊版行為,除非您已確實瞭解特定規則的用途,否則不建議這麼做。詳情請參閱 #2475

execpathsrootpathsrlocationpathslocations 分別是 execpathrootpathrlocationpathslocation 的複數變化。這些元件支援產生多個輸出內容的標籤,在此情況下,每個輸出內容都會以空格分隔。零輸出規則和格式錯誤的標籤會導致建構錯誤。

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

標籤不一定要採用標準格式:foo:foo//somepkg:foo 等。

自訂變數

任何標示為「符合『建立變數』替代變數」的屬性都能參照自訂「Make」變數,但目標必須依賴定義這些變數的其他目標。

除非是有充分理由將變數烘焙為核心 Bazel 的做法,否則建議您一律自訂所有變數。省去了 Bazel 必須載入成本高昂的依附元件,從而避免使用消耗 tar 的變數的問題。

C++ 工具鍊變數

下列在 C++ 工具鍊規則中定義這些定義,並適用於任何設定了 toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"] (或主機工具鍊對等項目 "@bazel_tools//tools/cpp:current_cc_host_toolchain") 的規則。有些規則 (例如 java_binary) 會在規則定義中加入了 C++ 工具鍊。並自動繼承這些變數。

內建 C++ 規則比「對其執行編譯器」更為複雜。為了支援與 *SAN、ThinLTO 等多樣化的編譯模式,以及不含/不含模組,同時提供經過精細最佳化的二進位檔,同時支援在多個平台上快速執行測試,內建規則會大幅縮短確保針對可能的多個內部動作分別設定正確的輸入、輸出和指令列旗標。

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

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

    強烈建議您一律使用 CC_FLAGS 搭配 CC。無法承擔風險。

  • CC_FLAGS:供 C/C++ 編譯器使用的最小數量標記,可由 genRule 使用。請特別注意,如果 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 封裝和合併實作。

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

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

Starlark 定義的變數

規則和工具鍊寫入者可以傳回 TemplateVariableInfo 提供者,藉此定義完全的自訂變數。然後,任何透過 toolchains 屬性依附於這些規則的規則皆可讀取其值:

查看 Starlark 定義的變數範例