Bazel 支援外部依附元件和來源檔案 (文字和二進位檔),這些檔案用於建構作業,但並非來自工作區。例如,可以是 GitHub 存放區中代管的規則集、Maven 構件,或本機電腦上目前工作區外的目錄。
自 Bazel 6.0 起,您可以使用兩種方式透過 Bazel 管理外部依附元件:傳統的以存放區為主的 WORKSPACE
系統,以及較新的以模組為主的 MODULE.bazel
系統 (代號為 Bzlmod,並透過 --enable_bzlmod
旗標啟用)。這兩個系統可以一起使用,但 Bzlmod 會在日後的 Bazel 版本中取代 WORKSPACE
系統,請參閱 Bzlmod 遷移指南,瞭解如何遷移。
本文將說明 Bazel 中外部依附元件管理的概念,然後再詳細介紹這兩個系統。
概念
存放區
含有 WORKSPACE
或 WORKSPACE.bazel
檔案的目錄,內含要在 Bazel 建構作業中使用的來源檔案。通常會簡稱為「repo」repo。
主要存放區
目前 Bazel 指令執行的存放區。
工作區
所有 Bazel 指令都會在同一個主要存放區中執行,並共用環境。
請注意,從歷史來看,「存放區」和「工作區」的概念一直混淆不清;「工作區」一詞通常是指主要存放區,有時甚至用做「存放區」的同義詞。
正規存放區名稱
存放區可供定址的正規名稱。在工作區的脈絡中,每個存放區都有單一標準名稱。如果存放區中的目標標準名稱為 canonical_name
,則可透過標籤 @@canonical_name//pac/kage:target
(請注意雙 @
) 進行定址。
主要存放區的正式名稱一律為空字串。
存放區名稱
存放區在特定其他存放區環境中可定址的名稱。
這可以視為存放區的「暱稱」:在存放區 alice
的環境中,具有正式名稱 michael
的存放區可能具有顯而易見的名稱 mike
,但在存放區 bob
的環境中,可能具有顯而易見的名稱 mickey
。在這種情況下,michael
內的目標可在 alice
的環境中,透過標籤 @mike//pac/kage:target
進行定址 (請注意單一 @
)。
反過來說,這可以視為「存放區對應」:每個存放區都會維護從「顯而易見的存放區名稱」到「標準存放區名稱」的對應。
存放區規則
存放區定義的結構,會告知 Bazel 如何具體化存放區。舉例來說,可以是「從特定網址下載並解壓縮 zip 封存檔」、「擷取特定 Maven 構件並設為 java_import
目標」,或只是「建立本機目錄的符號連結」。每個存放區都是透過呼叫存放區規則並提供適當數量的引數定義。
如要進一步瞭解如何編寫自己的存放區規則,請參閱存放區規則。
目前最常見的存放區規則是 http_archive
,可從網址下載並解壓縮封存檔,以及 local_repository
,可符號連結已是 Bazel 存放區的本機目錄。
擷取存放區
透過執行相關聯的 repo 規則,在本地磁碟上提供 repo 的動作。工作區中定義的存放區必須先擷取,才能在本機磁碟上使用。
通常 Bazel 只會在需要存放區中的項目,且尚未擷取存放區時,才會擷取存放區。如果先前已擷取存放區,只有在定義變更時,Bazel 才會重新擷取。
目錄版面配置
擷取完成後,您可以在輸出基準的子目錄 external
中找到存放庫,並以正規名稱命名。
您可以執行下列指令,查看具有標準名稱 canonical_name
的存放區內容:
ls $(bazel info output_base)/external/ canonical_name
使用 Bzlmod 管理外部依附元件
Bzlmod 是新的外部依附元件子系統,無法直接與存放區定義搭配使用。而是從模組建構依附元件圖表,在圖表上執行擴充功能,並據此定義存放區。
Bazel 模組是 Bazel 專案,可有多個版本,每個版本都會發布所依附其他模組的中繼資料。模組的存放區根目錄必須有 MODULE.bazel
檔案,位於 WORKSPACE
檔案旁邊。這個檔案是模組的資訊清單,會宣告模組名稱、版本、依附元件清單等資訊。以下是基本範例:
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")
模組只能列出直接依附元件,Bzlmod 會在 Bazel 登錄檔 (預設為 Bazel Central Registry) 中查詢這些依附元件。登錄檔會提供依附元件的 MODULE.bazel
檔案,讓 Bazel 能夠在執行版本解析前,探索整個遞移相依關係圖。
版本解析完成後 (為每個模組選取一個版本),
Bazel 會再次查詢登錄檔,瞭解如何為每個模組定義存放區
(在大多數情況下,會使用 http_archive
)。
模組也可以指定稱為「標記」的自訂資料片段,這些資料片段會在模組解析後由模組擴充功能使用,以定義其他存放區。這些擴充功能的功能與存放區規則類似,可執行檔案 I/O 和傳送網路要求等動作。除了其他功能外,這些規則還可讓 Bazel 與其他套件管理系統互動,同時遵守從 Bazel 模組建構的依附元件圖。
Bzlmod 的外部連結
- bazelbuild/examples 中的 Bzlmod 用法範例
- Bazel 外部依附元件大改造 (原始 Bzlmod 設計文件)
- BazelCon 2021 演講:Bzlmod
- Bazel 社群日 Bzlmod 講座
使用 WORKSPACE
定義存放區
過去,您可以在 WORKSPACE
(或 WORKSPACE.bazel
) 檔案中定義存放區,藉此管理外部依附元件。這個檔案的語法與 BUILD
檔案類似,但採用的是存放區規則,而非建構規則。
以下程式碼片段範例說明如何在 WORKSPACE
檔案中使用 http_archive
存放區規則:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
這個程式碼片段定義的存放區正式名稱為 foo
。在 WORKSPACE
系統中,預設情況下,存放區的正式名稱也是所有其他存放區的顯示名稱。
如要查看 WORKSPACE
檔案中可用的函式完整清單,請參閱這篇文章。
WORKSPACE
系統的缺點
自 WORKSPACE
系統推出以來,使用者回報了許多痛點,包括:
- Bazel 不會評估任何依附元件的
WORKSPACE
檔案,因此除了直接依附元件外,所有遞移依附元件都必須在主要存放區的WORKSPACE
檔案中定義。 - 為解決這個問題,專案採用了「deps.bzl」模式,其中定義了巨集,而巨集又定義了多個存放區,並要求使用者在
WORKSPACE
檔案中呼叫這個巨集。- 這會產生自己的問題:巨集無法
load
其他.bzl
檔案,因此這些專案必須在這個「deps」巨集中定義其遞移依附元件,或讓使用者呼叫多個分層「deps」巨集,以解決這個問題。 - Bazel 會依序評估
WORKSPACE
檔案。此外,依附元件是使用含網址的http_archive
指定,不含任何版本資訊。也就是說,如果出現菱形依附元件 (A
依附於B
和C
;B
和C
都依附於不同版本的D
),就無法可靠地執行版本解析。
- 這會產生自己的問題:巨集無法
由於 WORKSPACE 有缺點,Bzlmod 將在日後的 Bazel 版本中取代舊版 WORKSPACE 系統。請參閱 Bzlmod 遷移指南,瞭解如何遷移至 Bzlmod。