使用平台進行建構

回報問題 查看來源

Bazel 提供複雜的支援,可為平台工具鍊建立模型。如要將這項功能與實際專案整合,您需要在程式碼擁有者、規則維護人員和 Bazel 核心開發人員之間謹慎合作。

本頁將概述平台的用途,並說明如何利用平台進行建構。

tl;dr:可使用 Bazel 的平台和工具鍊 API,但必須等到所有語言規則、select() 和其他舊版參照更新之後,才能在所有位置運作。這項工作仍在持續進行中。最終,所有版本都是以平台為基礎。請參閱下方說明,瞭解建構作業的適用範圍。

如需更正式的說明文件,請參閱:

背景

我們推出平台工具鍊標準化軟體專案鎖定不同機器的方式,並以合適的語言工具進行建構。

Bazel 的原因是。觀察後,語言維護人員「已經」以不相容性的方式臨時執行這項作業,藉此激發靈感。舉例來說,C++ 規則會使用 --cpu--crosstool_top 設定建構作業的目標 CPU 和 C++ 工具鍊。這兩個例子都未正確建立「平台」模型歷史上嘗試這樣做會使版本難以執行,並導致建構不準確。這些標記也無法控制 Java 編譯,這種編譯方式會透過 --java_toolchain 發展自己的獨立介面。

Bazel 適用於大型的多語言多平台專案。這需要針對這些概念提供更多原則支援,包括可促進語言和專案互通性的明確 API。這就是這些新的 API 的用途

遷移

平台和工具鍊 API 只有在專案實際使用時才會運作。這部分較為簡單,因為專案的規則邏輯、工具鍊、依附元件和 select() 必須支援這些邏輯。這需要謹慎的遷移序列,才能讓所有專案及其依附元件正常運作。

舉例來說,Bazel 的 C++ 規則支援平台。但 Apple 規則則不會。您的 C++ 專案可能並不在乎 Apple。但有些人可能會這麼做,因此還不適合全面支援所有 C++ 版本的平台。

本頁其餘部分會說明這個遷移順序,以及專案何時可採用的方式和時機。

目標

當所有專案使用以下格式建構時,Bazel 的平台遷移作業即告完成:

bazel build //:myproject --platforms=//:myplatform

這表示:

  1. 專案使用的規則可以從 //:myplatform 推論正確的工具鍊。
  2. 專案依附元件使用的規則可從 //:myplatform 推論正確的工具鍊。
  3. 您可用的專案 (視您的支援類型而定) //:myplatform「或是」專案支援舊版 API (例如 --crosstool_top)。
  4. //:myplatform 會參照 [common 宣告][Common Platform 宣告]{: .external} (共 CPUOS),以及其他支援自動跨專案相容性的泛型概念。
  5. 所有相關專案的 select() 都能瞭解 //:myplatform 隱含的機器屬性。
  6. //:myplatform 會定義在一個明確且可重複使用的位置:如果平台專屬於您的專案,請在專案存放區中定義這個平台,否則可在使用這個平台的所有專案找到它。

達成這個目標後,舊的 API 將立即移除。之後就會成為專案選擇平台和工具鍊的標準方式。

我該使用平台嗎?

如果您只想建構或交叉編譯專案,應按照專案的官方說明文件操作。

如果您是專案、語言或工具鍊維護人員,最終會想要支援新的 API。無論您是等待全球遷移作業完成,還是提早選擇加入,都取決於您的具體價值 / 費用需求:

價值

  • 您可以select() 或選擇所關注特定屬性的工具鍊,而非 --cpu 等硬式編碼旗標。例如,多個 CPU 可支援相同的指令集
  • 較正確的版本。如果您在上述範例中為 --cpu 執行 select(),然後新增支援相同指令集的新 CPU,select() 就會無法辨識新的 CPU。不過平台上的 select() 仍然正確。
  • 更簡便的使用者體驗。所有專案都瞭解:--platforms=//:myplatform。不需要在指令列中使用多個語言專用的標記。
  • 語言設計更簡潔。所有語言都會共用一個通用 API,用於定義工具鍊、使用工具鍊,以及為平台選取合適的工具鍊。
  • 如果目標與目標平台不相容,您可以在建構和測試階段「略過」

費用

  • 依附專案尚未支援平台,可能無法與您的平台自動搭配使用。
  • 這些項目可能需要額外的暫時性維護
  • 如要同時使用新版和舊版 API,需要更謹慎的使用者指引,以免混淆。
  • OSCPU常見屬性的標準定義仍在不斷演變,因此可能需要額外的初始貢獻。
  • 語言特定工具鍊的標準定義目前仍在不斷發展,可能需要額外的初始貢獻。

API 審查

platform 是一組 constraint_value 目標

platform(
    name = "myplatform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

constraint_value 是機器屬性。相同「種類」的值會歸入同一個 constraint_setting

constraint_setting(name = "os")
constraint_value(
    name = "linux",
    constraint_setting = ":os",
)
constraint_value(
    name = "mac",
    constraint_setting = ":os",
)

toolchain星形規則。其屬性會宣告語言工具 (例如 compiler = "//mytoolchain:custom_gcc")。提供者會將這項資訊傳送至需要使用這些工具建立的規則。

工具鍊會宣告可目標 (target_compatible_with = ["@platforms//os:linux"]) 的機器 constraint_value,而該工具可執行的機器。exec_compatible_with = ["@platforms//os:mac"]

建構 $ bazel build //:myproject --platforms=//:myplatform 時,Bazel 會自動選取可在建構機器上執行的工具鍊,並建構 //:myplatform 的二進位檔。這就是「工具鍊解決方案」

您可以使用 register_toolchainsWORKSPACE 中註冊一組可用工具鍊,也可以在指令列中使用 --extra_toolchains 註冊。

詳情請參閱這裡

狀態

目前的平台支援因語言而異。Bazel 的所有主要規則都會移至平台不過這項程序需要一些時間才能完成。這有三個主要原因:

  1. 您必須更新規則邏輯,才能從新的工具鍊 API (ctx.toolchains) 取得工具資訊,並停止讀取舊版設定 (例如 --cpu--crosstool_top)。這個過程相對簡單。

  2. 工具鍊維護工具必須定義工具鍊,並讓使用者存取 (位於 GitHub 存放區和 WORKSPACE 項目中)。從技術上來說,這項工作就這麼簡單,但必須經過智慧整理,才能維持易於的使用者體驗。

    您也必須使用平台定義 (除非您為執行同一個 Bazel 的相同機器進行建構)。一般來說,專案應定義自己的平台。

  3. 您必須遷移現有專案。select()轉換功能也必須遷移。這是最大的挑戰。多語言專案尤其困難 (如果「所有」語言都無法讀取 --platforms,這可能會失敗)。

如果您要設計新的規則集,就必須從一開始就支援平台。這樣會自動使規則與其他規則和專案相容,並隨著平台 API 越來越普及而提高值。

常見的平台屬性

OSCPU 等跨專案通用的平台屬性,應透過標準的集中位置宣告。這有助於促進跨專案和跨語言相容性

舉例來說,如果 MyAppconstraint_value @myapp//cpus:arm 上有 select(),而 SomeCommonLib@commonlib//constraints:arm 上設有 select(),這樣這些程式碼就會以不相容的條件觸發「實驗組」模式。

全域通用屬性會在 @platforms 存放區中宣告 (因此上述範例的標準標籤為 @platforms//cpu:arm)。您應在各語言的存放區中宣告慣用語言屬性。

預設平台

一般而言,專案擁有者應定義明確的平台,來說明他們要建構的機器類型。然後透過 --platforms 觸發。

如未設定 --platforms,Bazel 會預設為代表本機建構機器的 platform。這是在 @local_config_platform//:host 自動產生,因此不需要明確定義。這會將本機電腦的 OSCPU 對應至 @platforms 中宣告的 constraint_value

C++

設定 --incompatible_enable_cc_toolchain_resolution 時,Bazel 的 C++ 規則會使用平台來選取工具鍊 (#7260)。

這表示您可以使用下列指令設定 C++ 專案:

bazel build //:my_cpp_project --platforms=//:myplatform

而不是舊版:

bazel build //:my_cpp_project` --cpu=... --crosstool_top=...  --compiler=...

如果專案本身是 C++,且不受非 C++ 專案依賴,只要 select轉換相容,您就能安全地使用平台。如需更多指引,請參閱 #7260設定 C++ 工具鍊

這個模式預設為停用。這是因為 Apple 專案仍會使用 --cpu--crosstool_top 設定 C++ 依附元件 (範例)。因此這取決於遷移至平台的 Apple 規則。

Java

Bazel 的 Java 規則會使用平台。

這會取代舊版標記 --java_toolchain--host_java_toolchain--javabase--host_javabase

如要瞭解如何使用設定標記,請參閱 Bazel 和 Java 手冊。詳情請參閱設計文件

如果您仍在使用舊版標記,請按照問題 #7849 中的遷移程序操作。

Android

設定 --incompatible_enable_android_toolchain_resolution 時,Bazel 的 Android 規則會使用平台來選取工具鍊。

這項功能預設為停用。但遷移作業已順利進行。

蘋果

Bazel 的 Apple 規則尚未支援特定平台可選取 Apple 工具鍊。

也不支援支援平台的 C++ 依附元件,因為這類依附元件使用舊版 --crosstool_top 設定 C++ 工具鍊。在遷移完成之前,您可以將 Apple 專案與支援插座的 C++ 搭配使用,以及平台對應 (範例)。

其他語言

如要為新語言設計規則,請使用平台選取語言的工具鍊。如需詳盡的逐步操作說明,請參閱工具鍊說明文件

select()

專案可以select()針對目標constraint_value目標完成,但無法針對整個平台。這麼做是刻意讓 select() 盡可能支援各種機器。具有特定來源的ARM特定來源的程式庫應支援所有 ARM所有支援的機器,除非有更具體的理由。

如要選取一或多個 constraint_value,請使用:

config_setting(
    name = "is_arm",
    constraint_values = [
        "@platforms//cpu:arm",
    ],
)

這相當於在 --cpu 上選擇的傳統方式:

config_setting(
    name = "is_arm",
    values = {
        "cpu": "arm",
    },
)

詳情請參閱這篇文章

--cpu--crosstool_top 等的 select 無法辨識--platforms。將專案遷移至平台時,您必須將專案轉換為 constraint_values,或使用平台對應,在遷移期間支援兩種樣式。

轉場

Starlark 轉場效果會將標記變更成建構圖表的各個部分。如果專案使用的轉換作業會設定 --cpu--crossstool_top 或其他舊版旗標,讀取 --platforms 的規則不會看到這些變更。

將專案遷移至平台時,您必須將 return { "//command_line_option:cpu": "arm" } 等變更轉換為 return { "//command_line_option:platforms": "//:my_arm_platform" },或使用平台對應,在遷移視窗支援這兩種樣式。

目前的平台使用方式

如果您只想建構或交叉編譯專案,應按照專案的官方說明文件操作。要決定與平台整合的方式和時機,以及能創造的價值,全由語言和專案維護人員決定。

如果您是專案、語言或工具鍊維護人員,且您的建構作業預設未使用平台,則除了等待全域遷移作業之外,還有三種選項:

  1. 找到專案語言的「use platform」標記 (如果他們有),然後執行您需要的任何測試,查看關注的專案是否有效。

  2. 如果重視的專案仍依附於舊版旗標 (例如 --cpu--crosstool_top),請與 --platforms 搭配使用:

    bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
    

    這會有一些維護費用 (您必須手動確認設定一致)。但在沒有消化轉換的情況下,此方法應能發揮效用。

  3. --cpu 樣式設定對應至對應的平台,進而編寫平台對應來支援這兩種樣式。

平台對應

平台對應是一個臨時 API,可讓採用平台和舊版的邏輯共存於後者的淘汰期。

平台對應是將 platform() 對應到一組對應舊版旗標或反向標記的對應。例如:

platforms:
  # Maps "--platforms=//platforms:ios" to "--cpu=ios_x86_64 --apple_platform_type=ios".
  //platforms:ios
    --cpu=ios_x86_64
    --apple_platform_type=ios

flags:
  # Maps "--cpu=ios_x86_64 --apple_platform_type=ios" to "--platforms=//platforms:ios".
  --cpu=ios_x86_64
  --apple_platform_type=ios
    //platforms:ios

  # Maps "--cpu=darwin --apple_platform_type=macos" to "//platform:macos".
  --cpu=darwin
  --apple_platform_type=macos
    //platforms:macos

Bazel 會使用這項做法來確保整個建構作業中 (包括平台和舊版) 的所有設定皆一致地套用,包括透過轉換

根據預設,Bazel 會讀取工作區根目錄中 platform_mappings 檔案的對應關係。您也可以設定 --platform_mappings=//:my_custom_mapping

詳情請參閱這裡

問題

如有關於遷移時程的一般支援和問題,請聯絡 bazel-discuss@googlegroups.com 或相關規則的擁有者。

如要討論平台/工具鍊 API 的設計和演進,請與 bazel-dev@googlegroups.com 聯絡。

另請參閱