Bazel 可以在各種硬體、作業系統及 使用許多不同版本的建構工具,例如 連結器和編譯器為了協助管理複雜性,Bazel 有個概念: constraints 和 platforms。限制是指建構或執行的維度 在您的實際工作環境中,CPU 架構、是否存在 就沒有 GPU,或是系統安裝的編譯器版本平台是一種 這些限制條件的命名選項集合,代表特定的 為某些環境提供可用的資源
將環境建立成平台模型可協助 Bazel 自動選取 適合 工具鍊 來建立建構動作平台也可以與 config_setting 撰寫可設定屬性的規則。
Bazel 可辨識平台可能提供的三個角色:
- Host:Bazel 本身的執行平台。
- 「Execution」:建構工具會在這個平台執行建構動作,以執行建構動作。 產生中繼和最終輸出內容
- 「Target」:儲存並執行最終輸出內容的平台。
Bazel 支援下列與平台相關的建構情境:
單一平台建構 (預設):主機、執行和目標平台 保持不變例如,在 Intel x64 CPU
跨編譯版本:主機和執行平台相同,但 目標平台不同例如在 macOS 上建構 iOS 應用程式 它是在 MacBook Pro 上運作
多平台版本 - 主機、執行和目標平台都是 也不一樣
定義限制和平台
平台可用選項的空間是以
constraint_setting
和
BUILD
檔案中的 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 還隨附下列特殊的平台定義:
@platforms//host
(別名為 @bazel_tools//tools:host_platform
)。這是
自動偵測的主機平台值 -
。
指定建構作業的平台
您可以使用下列指令,為建構作業指定主機和目標平台 指令列標記:
--host_platform
- 預設為@bazel_tools//tools:host_platform
- 這個目標會別名為
@platforms//host
,而由存放區提供支援 規則,可偵測主機 OS 和 CPU 並寫入平台目標。 - 還有
@platforms//host:constraints.bzl
,會在公開位置 稱為HOST_CONSTRAINTS
的陣列,可用於其他 BUILD Starlark 檔案。
- 這個目標會別名為
--platforms
:預設為代管平台- 也就是說,如果沒有設定其他旗標
@platforms//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"],
}),
)
上述可以解釋如下:
- 指定 macOS 時,目標沒有任何限制。
- 指定 Linux 時,目標沒有任何限制。
- 否則,目標會包含
@platforms//:incompatible
限制。由於@platforms//:incompatible
不屬於任何平台,目標是 就會視為不相容
如要讓限制條件更清楚易讀,請使用
skylib 的
selects.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 cquery
的 Starlark 輸出內容
格式來區分
不相容的目標
可用來篩除不相容的指定目標。以下範例 系統只會顯示相容目標的標籤。不相容的目標如下: 因此無法列印。
$ cat example.cquery
def format(target):
if "IncompatiblePlatformProvider" not in providers(target):
return target.label
return ""
$ bazel cquery //... --output=starlark --starlark:file=example.cquery
已知問題
不相容的目標忽略瀏覽權限 限制。