Bazel 支援複雜的平台和工具鍊模型。如要將這項功能整合至實際專案,程式碼擁有者、規則維護人員和核心 Bazel 開發人員必須密切合作。
本頁面會簡要說明平台用途,並展示如何使用平台建構應用程式。
簡而言之:Bazel 的平台和工具鍊 API 可供使用,但必須更新所有語言規則、select()
和其他舊版參照,才能在所有位置運作。這項工作仍在持續進行中。最終所有版本都會以平台為基礎。
請參閱下文,瞭解您的建構版本適合哪種測試。
如需更正式的說明文件,請參閱:
背景
我們導入了平台和工具鍊,標準化軟體專案的目標機器,並使用適當的語言工具建構。
這是 Bazel 相對較新的功能。我們發現語言維護人員已經在以不相容的臨時方式執行這項作業,因此受到啟發。舉例來說,C++ 規則會使用 --cpu
和 --crosstool_top
設定建構作業的目標 CPU 和 C++ 工具鍊。這兩者都無法正確模擬「平台」。過去嘗試這麼做時,會導致建構作業不準確且令人尷尬。這些旗標也不會控管 Java 編譯作業,因為 Java 編譯作業已發展出自己的獨立介面 --java_toolchain
。
Bazel 適用於大型、多語言、多平台專案。因此,我們需要為這些概念提供更具原則性的支援,包括鼓勵語言和專案互通性的明確 API。這些新 API 的用途就在於此。
遷移
平台和工具鍊 API 只有在專案實際使用時才會運作。這並非易事,因為專案的規則邏輯、工具鍊、依附元件和 select()
都必須支援這些功能。因此必須謹慎地依序遷移,才能確保所有專案及其依附元件正常運作。
舉例來說,Bazel 的 C++ 規則支援平台。但 Apple 規則並非如此。您的 C++ 專案可能不支援 Apple。但其他建構作業可能需要。因此,目前還不適合為所有 C++ 建構作業全域啟用平台。
本頁面其餘內容將說明這項遷移程序,以及專案的適用時間和方式。
目標
當所有專案都以以下形式建構時,Bazel 的平台遷移作業即完成:
bazel build //:myproject --platforms=//:myplatform
這表示:
- 專案使用的規則可以從
//:myplatform
推斷正確的工具鍊。 - 專案依附元件使用的規則可以從
//:myplatform
推斷正確的工具鍊。 - 視情況,專案支援
//:myplatform
或專案支援舊版 API (例如--crosstool_top
)。 //:myplatform
參照 [常見宣告][Common Platform Declaration]{: .external},CPU
、OS
和其他支援自動跨專案相容性的通用概念。- 所有相關專案
select()
瞭解//:myplatform
所隱含的機器屬性。 //:myplatform
定義在清楚且可重複使用的位置:如果平台是專案專屬,則定義在專案的存放區中;否則定義在所有可能使用這個平台的專案都能找到的位置。
達成目標後,系統就會移除舊版 API。然後,這會成為專案選取平台和工具鍊的標準方式。
我該使用平台嗎?
如果只是想建構或交叉編譯專案,請參閱專案的官方文件。
如果您是專案、語言或工具鍊維護人員,最終會需要支援新版 API。您要等到全球遷移作業完成,還是選擇提早加入,取決於您的特定價值 / 成本需求:
值
- 您可以
select()
或選擇您關心的確切屬性,而不是--cpu
等硬式編碼標記。舉例來說,多個 CPU 可以支援相同的指令集。 - 建構更多正確的內容。如果您在上述範例中
select()
--cpu
,然後新增支援相同指令集的 CPU,select()
就無法辨識新的 CPU。但平台上的select()
仍正確無誤。 - 簡化使用者體驗。所有專案都瞭解:
--platforms=//:myplatform
。不需要在指令列上使用多個語言專屬的旗標。 - 語言設計更簡單。所有語言都共用一個 API,用於定義工具鍊、使用工具鍊,以及為平台選取合適的工具鍊。
- 如果目標與目標平台不相容,系統可能會在建構和測試階段略過目標。
費用
- 如果相依專案尚未支援平台,可能無法自動與您的專案搭配運作。
- 如要讓這些功能正常運作,可能需要額外的臨時維護作業。
- 新舊版 API 並存時,需要更謹慎地提供使用者指引,以免造成混淆。
- 常見屬性 (例如
OS
和CPU
) 的標準定義仍在演進中,可能需要額外的初始貢獻。 - 語言專屬工具鍊的標準定義仍在演進中,可能需要額外的初始貢獻。
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
建構二進位檔。這稱為「工具鍊解析」。
您可以在 WORKSPACE
中使用 register_toolchains
註冊可用的工具鍊組合,也可以在指令列中使用 --extra_toolchains
註冊。
如要深入瞭解,請參閱這篇文章。
狀態
目前各語言支援的平台有所不同。Bazel 的所有主要規則都會移至平台。但這項程序需要一些時間才能完成。主要有以下三個原因:
您必須更新規則邏輯,才能透過新的工具鍊 API (
ctx.toolchains
) 取得工具資訊,並停止讀取--cpu
和--crosstool_top
等舊版設定。這項作業相對簡單。工具鍊維護人員必須定義工具鍊,並讓使用者存取 (在 GitHub 存放區和
WORKSPACE
項目中)。這在技術上很簡單,但必須經過妥善整理,才能維持簡單的使用者體驗。您也需要平台定義 (除非您是為 Bazel 執行的同一部機器建構)。一般來說,專案應自行定義平台。
現有專案必須遷移,
select()
和轉換也必須遷移。這是最大的挑戰。如果專案包含多種語言,且所有語言都無法讀取--platforms
,則特別容易發生問題。
如果您要設計新的規則集,一開始就必須支援平台。這項功能會自動讓規則與其他規則和專案相容,隨著平台 API 越來越普及,價值也會隨之提升。
常見平台屬性
專案通用的平台屬性 (例如 OS
和 CPU
) 應在標準的集中位置宣告。這有助於跨專案和跨語言相容。
舉例來說,如果 MyApp 在 constraint_value
@myapp//cpus:arm
上有 select()
,而 SomeCommonLib 在 @commonlib//constraints:arm
上有 select()
,這些會以不相容的條件觸發「arm」模式。
全域通用屬性會在 @platforms
存放區中宣告 (因此上述範例的標準標籤為 @platforms//cpu:arm
)。語言通用屬性應在各自語言的存放區中宣告。
預設平台
一般來說,專案擁有者應定義明確的平台,說明要建構的機器類型。然後使用 --platforms
觸發這些事件。
如果未設定 --platforms
,Bazel 會預設為代表本機建構機器的 platform
。這項設定會在 @local_config_platform//:host
中自動產生,因此不必明確定義。這個項目會將本機的 OS
和 CPU
對應至 @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 規則會使用平台選取工具鍊。
這項功能預設為停用。但遷移作業已順利進行。
Apple
Bazel 的 Apple 規則目前不支援選取 Apple 工具鍊的平台。
此外,由於這些規則使用舊版 --crosstool_top
設定 C++ 工具鍊,因此不支援平台啟用的 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",
},
)
詳情請參閱這篇文章。
select
、--cpu
、--crosstool_top
等等不瞭解 --platforms
。將專案遷移至平台時,您必須將樣式轉換為 constraint_values
,或使用平台對應,在遷移期間同時支援這兩種樣式。
轉場
Starlark 轉換會變更建構圖表部分中的標記。如果專案使用的轉場效果會設定 --cpu
、--crossstool_top
或其他舊版標記,讀取 --platforms
的規則就不會看到這些變更。
將專案遷移至平台時,您必須轉換 return { "//command_line_option:cpu": "arm" }
等變更 (例如轉換為 return {
"//command_line_option:platforms": "//:my_arm_platform" }
),或使用平台對應,在遷移期間同時支援這兩種樣式。
如何使用現今的平台
如果只是想建構或交叉編譯專案,請參閱專案的官方文件。語言和專案維護人員可自行決定如何及何時與平台整合,以及整合後可帶來的價值。
如果您是專案、語言或工具鍊維護人員,且建構作業預設不使用平台,除了等待全域遷移外,您還有三種做法:
為專案語言開啟「使用平台」標記 (如有),並進行所需測試,確認您關心的專案是否正常運作。
如果您關心的專案仍依附於
--cpu
和--crosstool_top
等舊版標記,請搭配使用這些標記與--platforms
:bazel build //:my_mixed_project --platforms==//:myplatform --cpu=... --crosstool_top=...
這會產生一些維護費用 (您必須手動確保設定相符)。但如果沒有重新導向轉場,這應該會正常運作。
撰寫平台對應,將
--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 聯絡。