Bazel 提供精密的支援,可模擬平台和工具鍊,以便進行多架構和交叉編譯的建構作業。
本頁面會概述這項支援的狀態。
另請參閱:
狀態
C++
設定 --incompatible_enable_cc_toolchain_resolution
時,C++ 規則會使用平台選取工具鍊。
這表示您可以使用下列指令設定 C++ 專案:
bazel build //:my_cpp_project --platforms=//:myplatform
而非舊版:
bazel build //:my_cpp_project` --cpu=... --crosstool_top=... --compiler=...
這項功能會在 Bazel 7.0 (#7260) 中預設為啟用。
如要使用平台測試 C++ 專案,請參閱「遷移專案」和「設定 C++ 工具鍊」。
Java
Java 規則會使用平台來選擇工具鍊。
這會取代舊版旗標 --java_toolchain
、--host_java_toolchain
、--javabase
和 --host_javabase
。
詳情請參閱「Java 和 Bazel」。
Android
設定 --incompatible_enable_android_toolchain_resolution
時,Android 規則會使用平台選取工具鍊。
也就是說,您可以使用以下方式設定 Android 專案:
bazel build //:my_android_project --android_platforms=//:my_android_platform
而不是使用 --android_crosstool_top
、--android_cpu
和 --fat_apk_cpu
等舊版旗標
這項功能會在 Bazel 7.0 (#16285) 中預設為啟用。
如要透過平台測試 Android 專案,請參閱遷移專案。
Apple
Apple 規則不支援平台,且尚未排定支援時程。
您仍可使用平台 API 搭配 Apple 版本 (例如,在使用 平台對應時,以 Apple 規則和純 C++ 混合建構)。
其他語言
如果您擁有語言規則集,請參閱「遷移規則集」瞭解如何新增支援。
背景
平台和工具鍊的引入,是為了讓軟體專案以標準方式指定不同的架構和交叉編譯。
這項功能的靈感來自觀察到語言維護人員已以不相容的方式臨時執行這項操作。舉例來說,C++ 規則會使用 --cpu
和 --crosstool_top
宣告目標 CPU 和工具鍊。這兩種方法都無法正確模擬「平台」。這會產生不正確的建構作業。
Java、Android 和其他語言都為類似用途開發了各自的標記,但這些標記之間並未相互互動。這使得跨語言建構變得混淆又複雜
Bazel 適用於大型、多語言、多平台專案。同時,您需要針對這些概念提供更多原則支援,包括明確的標準 API。
需要遷移
升級至新 API 需要兩項工作:發布 API 並升級規則邏輯以便使用。
第一項作業已完成,但第二項仍在進行中。這包括確保已定義語言專屬平台和工具鍊、語言邏輯透過新 API 讀取工具鍊,而非 --crosstool_top
等舊版標記,以及 config_setting
在新的 API 上選取,而非舊版標記。
這項工作很簡單,但需要針對每種語言進行不同的努力,並為專案擁有者提供合理的警告,以便針對即將發生的變更進行測試。
這也是為何需要進行持續的遷移作業。
目標
所有使用以下形式建構的專案都會完成這項遷移作業:
bazel build //:myproject --platforms=//:myplatform
這表示:
- 專案規則會為
//:myplatform
選擇正確的工具鍊。 - 專案依附元件會為
//:myplatform
選擇適當的工具鍊。 //:myplatform
會參照CPU
、OS
和其他一般性、不依語言而異的屬性常見宣告- 所有相關
select()
都與//:myplatform
相符。 //:myplatform
是在清楚且可存取的位置定義:如果平台是專案專屬,則會在專案的 repo 中定義;如果平台是所有使用者專案都能找到的常用位置,則會在該位置定義
--cpu
、--crosstool_top
和 --fat_apk_cpu
等舊旗標會淘汰並立即移除。
最終,這會是架構的「唯一」設定方式。
遷移專案
如果您使用支援平台的語言進行建構,您的建構作業應已可搭配以下類似的叫用作業:
bazel build //:myproject --platforms=//:myplatform
如需詳細資訊,請參閱「狀態」和您語言的說明文件。
如果某種語言需要旗標才能啟用平台支援功能,您也必須設定該旗標。詳情請參閱「狀態」一節。
如要建構專案,請檢查下列項目:
//:myplatform
必須存在。由於不同專案指定的機器不同,因此定義平台通常是專案擁有者的責任。請參閱「預設平台」。您要使用的工具鍊必須存在。如果使用圖庫鏈,語言擁有者應提供註冊操作說明。如要編寫自己的自訂工具鍊,您必須在
MODULE.bazel
檔案中使用--extra_toolchains
進行register。如果您的版本混合了支援及不支援平台的語言,您可能需要建立平台對應,才能讓舊版語言與新的 API 搭配運作。詳情請參閱「平台對應」。
如果仍有問題,請與我們聯絡尋求協助。
預設平台
專案擁有者應明確定義平台,以說明他們要為哪些平台建構。然後使用 --platforms
觸發這些事件。
如果未設定 --platforms
,Bazel 預設會使用 platform
,代表本機建構機器。系統會在 @platforms//host
自動產生此值 (別名為 @bazel_tools//tools:host_platform
),因此您不必明確定義。它會將本機機器的 OS
和 CPU
對應至 @platforms
中宣告的 constraint_value
。
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" }
等變更,或是使用平台對應,在遷移期間支援這兩種樣式。
正在遷移規則集
如果您擁有規則集,並且想支援平台,則必須:
使用工具鍊 API 將規則邏輯解析工具鍊。請參閱工具鍊 API (
ctx.toolchains
)。選用:定義
--incompatible_enable_platforms_for_my_language
旗標,讓規則邏輯在遷移測試期間透過新 API 或--crosstool_top
等舊旗標交替解析工具鍊。定義組成平台元件的相關屬性。請參閱「常見的平台屬性」
定義標準工具鍊,並透過規則的註冊操作說明,讓使用者存取這些工具鍊 (詳情)
請確保
select()
和設定轉換支援平台。這是最大的挑戰。這對多語言專案來說特別棘手 (如果所有語言都無法讀取--platforms
,專案可能會失敗)。
如果您需要搭配不支援平台的規則,可能需要平台對應來彌補差距。
常見的平台屬性
OS
和 CPU
等跨語言平台屬性應在 @platforms
中宣告。這有助於促進共用、標準化和跨語言相容性。
您必須在規則存放區中宣告規則專屬的屬性。這樣一來,您就能清楚掌握規則負責的特定概念。
如果規則使用自訂用途的作業系統或 CPU,則應在規則的 repo 中宣告這些項目,而非在 @platforms
中。
平台對應
平台對應是暫時性的 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_x86_64 --apple_platform_type=macos" to "//platform:macos".
--cpu=darwin_x86_64
--apple_platform_type=macos
//platforms:macos
Bazel 會利用這項功能,確保所有設定 (包括平台和舊版設定) 都能在整個建構作業中一致套用,包括透過轉換。
根據預設,Bazel 會讀取工作區根目錄中 platform_mappings
檔案的對應關係。您也可以設定 --platform_mappings=//:my_custom_mapping
。
詳情請參閱平台對應設計。
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
是 Starlark 規則。其屬性會宣告語言的工具 (例如 compiler =
"//mytoolchain:custom_gcc"
)。其供應者會將這項資訊傳遞給需要使用這些工具建構的規則。
工具鏈會宣告可指定的機器 constraint_value
(target_compatible_with = ["@platforms//os:linux"]
),以及可執行工具的機器 (exec_compatible_with = ["@platforms//os:mac"]
)。
建構 $ bazel build //:myproject --platforms=//:myplatform
時,Bazel 會自動選取可在建構機器上執行的工具鍊,並為 //:myplatform
建構二進位檔。這就是「工具鍊解決方案」。
您可以使用 register_toolchains
在 MODULE.bazel
檔案中註冊可用的工具鍊組合,也可以使用 --extra_toolchains
在指令列中註冊。
詳情請參閱這篇文章。
問題
如需一般支援和遷移時程相關問題,請聯絡 bazel-discuss 或適當規則的擁有者。
如要討論平台/工具鍊 API 的設計和演進,請與 bazel-dev 聯絡。