平台

回報問題 查看原始碼 夜間 7.2 7.1 7.0 6.5 6.4

Bazel 可以在各種硬體、作業系統及 使用許多不同版本的建構工具,例如 連結器和編譯器為了協助管理複雜性,Bazel 有個概念: constraintsplatforms。限制是指建構或執行的維度 在您的實際工作環境中,CPU 架構、是否存在 就沒有 GPU,或是系統安裝的編譯器版本平台是一種 這些限制條件的命名選項集合,代表特定的 為某些環境提供可用的資源

將環境建立成平台模型可協助 Bazel 自動選取 適合 工具鍊 來建立建構動作平台也可以與 config_setting 撰寫可設定屬性的規則。

Bazel 可辨識平台可能提供的三個角色:

  • Host:Bazel 本身的執行平台。
  • 「Execution」:建構工具會在這個平台執行建構動作,以執行建構動作。 產生中繼和最終輸出內容
  • 「Target」:儲存並執行最終輸出內容的平台。

Bazel 支援下列與平台相關的建構情境:

  • 單一平台建構 (預設):主機、執行和目標平台 保持不變例如,在 Intel x64 CPU

  • 跨編譯版本:主機和執行平台相同,但 目標平台不同例如在 macOS 上建構 iOS 應用程式 它是在 MacBook Pro 上運作

  • 多平台版本 - 主機、執行和目標平台都是 也不一樣

定義限制和平台

平台可用選項的空間是以 constraint_settingBUILD 檔案中的 constraint_value 規則。 constraint_setting 會建立新維度, constraint_value 會建立指定維度的新值;所有人 可有效定義列舉及其可能的值。例如,下列 BUILD 檔案的程式碼片段導入系統 glibc 版本的限制 ,指的就是兩個可能的值。

constraint_setting(name = "glibc_version")

constraint_value(
    name = "glibc_2_25",
    constraint_setting = ":glibc_version",
)

constraint_value(
    name = "glibc_2_26",
    constraint_setting = ":glibc_version",
)

限制及相關值可以在 工作區由標籤參照,且受限於正常的顯示設定 控制項如果瀏覽權限允許,您就可以透過 定義自己的價值

platform 規則導入了新的平台,其中包含 特定限制值的選項 下列字串建立名為 linux_x86 的平台,表示其會描述任何 執行 Linux 作業系統的 x86_64 架構 glibc 2.25 版。(如要進一步瞭解 Bazel 的內建限制,請參閱下文)。

platform(
    name = "linux_x86",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
        ":glibc_2_25",
    ],
)

大致上實用的限制和平台

為了維持生態系統的一致性,Bazel 團隊會在 最熱門的 CPU 架構和作業環境的限制定義 有些人會將 Cloud Storage 視為檔案系統 但實際上不是這些都位於 https://github.com/bazelbuild/platforms.

Bazel 還隨附下列特殊的平台定義: @local_config_platform//:host。這是自動偵測的主機平台值: 。

指定建構作業的平台

您可以使用下列指令,為建構作業指定主機和目標平台 指令列標記:

  • --host_platform - 預設為 @local_config_platform//:host
    • @local_config_platform 是可偵測主機 OS 並 對平台目標進行 CPU 和寫入
    • 也會建立 @local_config_platform//:constraintz.bzl 稱為 HOST_CONSTRAINTS 的陣列,可用於其他 BUILD Starlark 檔案。
  • --platforms:預設為代管平台
    • 也就是說,如果沒有設定其他旗標 @local_config_platform//:host 是目標平台。
    • 如果已設定 --host_platform 而非 --platforms--host_platform 同時是主機和目標平台。

略過不相容的目標

針對特定目標平台建構應用程式時,通常會選擇略過 以及 YouTube 上永遠無法達成的目標舉例來說,您的 Windows 裝置 驅動程式在建構介面時,可能會產生許多編譯器錯誤 搭載 //... 的 Linux 機器。使用 target_compatible_with 屬性來告知 Bazel 哪個目標平台限制了程式碼。

這項屬性最簡單的應用方式,就是將指定目標限制在單一平台。 如果平台不符合所有條件,系統就不會為其建置目標 限制。以下範例將 win_driver_lib.cc 限制為 64 位元 Windows。

cc_library(
    name = "win_driver_lib",
    srcs = ["win_driver_lib.cc"],
    target_compatible_with = [
        "@platforms//cpu:x86_64",
        "@platforms//os:windows",
    ],
)

:win_driver_lib 與使用 64 位元 Windows 和 與所有其他版本不相容不相容性等同於遞移性。任何指定目標 而間接依附不相容的目標 不相容

在什麼情況下會略過目標?

如果系統判定目標不相容且包含在 作為目標模式擴展的一部分。例如下列兩個 叫用會略過目標模式展開中的任何不相容的目標。

$ bazel build --platforms=//:myplatform //...
$ bazel build --platforms=//:myplatform //:all

test_suite 中不相容的測試如下: 同樣地,如果在指令列中指定 test_suite --expand_test_suites。 換句話說,指令列上的 test_suite 目標的運作方式與 :all...。使用 --noexpand_test_suites 會阻止系統展開和造成原因 test_suite 目標含有不相容的測試,因此也不相容。

在指令列中明確指定不相容的目標,會導致 錯誤訊息和建構失敗。

$ bazel build --platforms=//:myplatform //:target_incompatible_with_myplatform
...
ERROR: Target //:target_incompatible_with_myplatform is incompatible and cannot be built, but was explicitly requested.
...
FAILED: Build did NOT complete successfully

系統會略過不相容的明確目標, 已啟用「--skip_incompatible_explicit_targets」。

較能表達的限制

如果您希望更靈活地表達限制,請使用 @platforms//:incompatible constraint_value 但任何平台都能滿足

select()@platforms//:incompatible 表示較複雜的限制。適用對象 例如,使用它實作基本的 OR 邏輯。下列程式碼會標示程式庫 可與 macOS 和 Linux 相容,但不支援其他平台。

cc_library(
    name = "unixish_lib",
    srcs = ["unixish_lib.cc"],
    target_compatible_with = select({
        "@platforms//os:osx": [],
        "@platforms//os:linux": [],
        "//conditions:default": ["@platforms//:incompatible"],
    }),
)

上述可以解釋如下:

  1. 指定 macOS 時,目標沒有任何限制。
  2. 指定 Linux 時,目標沒有任何限制。
  3. 否則,目標會包含 @platforms//:incompatible 限制。由於 @platforms//:incompatible 不屬於任何平台,目標是 就會視為不相容

如要讓限制條件更清楚易讀,請使用 skylibselects.with_or()

您可以透過類似方式表達不相容性,以下範例 是指與 ARM「除外」所有內容相容的程式庫。

cc_library(
    name = "non_arm_lib",
    srcs = ["non_arm_lib.cc"],
    target_compatible_with = select({
        "@platforms//cpu:arm": ["@platforms//:incompatible"],
        "//conditions:default": [],
    }),
)

使用 bazel cquery 偵測不相容的目標

您可以使用 IncompatiblePlatformProvider bazel cqueryStarlark 輸出內容 格式來區分 不相容的目標

可用來篩除不相容的指定目標。以下範例 系統只會顯示相容目標的標籤。不相容的目標如下: 因此無法列印。

$ cat example.cquery

def format(target):
  if "IncompatiblePlatformProvider" not in providers(target):
    return target.label
  return ""


$ bazel cquery //... --output=starlark --starlark:file=example.cquery

已知問題

不相容的目標忽略瀏覽權限 限制。