外部依附元件總覽

7.3 · 7.2 · 7.1 · 7.0 · 6.5

Bazel 支援外部依附元件,也就是在建構作業中使用的來源檔案 (文字和二進位檔),但這些檔案並非來自您的工作區。舉例來說,這些規則集可能會託管在 GitHub 存放區、Maven 構件或本機電腦上 (不在目前工作區內)。

自 Bazel 6.0 起,您可以透過 Bazel 管理外部依附元件,方法有兩種方式:傳統、以存放區為中心的 WORKSPACE 系統,以及著重於模組的較新 MODULE.bazel 系統 (代碼稱為 Bzlmod,並以標記 --enable_bzlmod 啟用)。這兩個系統可以一起使用,但 Bzlmod 如何在日後的 Bazel Bz 版本中替換 WORKSPACE 系統。

本文件將說明 Bazel 中外部依附元件管理的相關概念,再依序深入說明這兩個系統。

概念

存放區

包含 WORKSPACEWORKSPACE.bazel 檔案的目錄,其中包含要在 Bazel 建構中使用的原始碼檔案。通常會縮短為只有 repo

主要存放區

目前正在執行 Bazel 指令的存放區。

工作區

在同一個主要存放區執行的所有 Bazel 指令共用的環境。

請注意,過去「存放區」和「工作區」的概念已經過合併,經常用來指稱主要存放區,有時甚至用來做為「存放區」的同義詞。

標準存放區名稱

存放區可供存取的正規名稱。在工作區的背景資訊中,每個存放區都有一個標準名稱。在名稱為 canonical_name 的存放區中,可以使用標籤 @@canonical_name//pac/kage:target 來處理目標 (請注意雙 @)。

主要存放區一律以空字串做為標準名稱。

明顯的存放區名稱

存放區名稱可透過其他特定存放區來定址。這可以視為儲存庫的「別名」:具有標準名稱 michael 的儲存庫在 alice 儲存庫的上下文中可能會有顯式名稱 mike,但在 bob 儲存庫的上下文中可能會有顯式名稱 mickey。在這種情況下,michael 內的目標可透過 alice 中的 @mike//pac/kage:target 標籤來解決 (請注意單一 @)。

反之,這可以視為存放區對應:每個存放區都會維護從「明顯的存放區名稱」到「正式的存放區名稱」的對應關係。

存放區規則

存放區定義的結構定義,可告知 Bazel 如何實現存放區。舉例來說,您可以使用「從特定網址下載並解壓縮 ZIP 封存檔」,或「擷取特定 Maven 成果物,並將其用作 java_import 目標」,或是簡單地使用「建立本機目錄的符號連結」。每個 repo 都是透過呼叫 repo 規則,並使用適當數量的引數定義

如要進一步瞭解如何編寫自訂存放區規則,請參閱「存放區規則」。

目前為止,最常見的存放區規則是 http_archive,用於從網址下載封存檔案並加以擷取,而 local_repository (後者會符號連結已位於 Bazel 存放區的本機目錄)。

擷取存放區

透過執行相關聯的 repo 規則,在本機磁碟上提供 repo 的動作。在擷取之前,工作區中定義的 repo 無法在本機磁碟上使用。

通常,Bazel 只會在需要存放區的內容,且尚未擷取存放區時,才擷取存放區。如果先前已擷取該存放區,Bazel 只會在定義有所變更時重新擷取。

目錄版面配置

擷取後,您可以在輸出基地的子目錄 external 中,以正規名稱找到該存放區。

您可以執行下列指令,查看名稱為 canonical_name 的標準化名稱的存放區內容:

ls $(bazel info output_base)/external/ canonical_name 

使用 Bzlmod 管理外部依附元件

新的外部依附元件子系統 Bzlmod 無法直接與 repo 定義搭配使用。而是從模組建構依附元件圖表,在圖表上執行擴充功能,並據此定義 repos。

Bazel 模組是可擁有多個版本的 Bazel 專案,每個版本都會發布關於所依附其他模組的中繼資料。模組必須在其存放區根目錄中,WORKSPACE 檔案旁邊,有 MODULE.bazel 檔案。這個檔案是模組的資訊清單,會宣告模組的名稱、版本、依附元件清單和其他資訊。以下是基本範例:

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 中央登錄表。登錄會提供依附元件的 MODULE.bazel 檔案,讓 Bazel 在執行版本解析前,先找出整個傳遞式相依關係圖。

在版本解析完成後,Bazel 會為每個模組選取一個版本,然後再次諮詢註冊中心,瞭解如何為每個模組定義一個存放區 (在大多數情況下,使用 http_archive)。

模組也可以指定稱為「標記」的自訂資料片段,這些標記會在模組解析後由模組擴充功能使用,用於定義其他存放區。這些擴充功能的功能類似於 repo 規則,可執行檔案 I/O 和傳送網路要求等動作。除了其他功能外,這些模組還可讓 Bazel 與其他套件管理系統互動,同時遵循 Bazel 模組建立的依附元件圖。

使用 WORKSPACE 定義 repos

過去,您可以透過在 WORKSPACE (或 WORKSPACE.bazel) 檔案中定義 repos,來管理外部依附元件。這個檔案的語法與 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 系統中,根據預設,Repo 的正式名稱也是所有其他 Repo 的顯示名稱。

WORKSPACE 系統的缺點

WORKSPACE 系統推出以來,使用者回報了許多困擾,包括:

  • Bazel 不會評估任何依附元件的 WORKSPACE 檔案,因此除了直接依附元件外,所有傳遞依附元件都必須在主存放區的 WORKSPACE 檔案中定義。
  • 為解決這個問題,專案採用了「deps.bzl」模式,其中定義的巨集會依序定義多個存放區,並要求使用者在 WORKSPACE 檔案中呼叫這個巨集。
    • 這會產生一些問題:巨集無法 load 其他 .bzl 檔案,因此這些專案必須在這個「deps」巨集中定義其傳遞依附元件,或是讓使用者呼叫多個分層「deps」巨集,以解決這個問題。
    • Bazel 會依序評估 WORKSPACE 檔案。此外,依附元件會使用 http_archive 和網址指定,不含任何版本資訊。也就是說,在菱形依附元件情況下,沒有可靠的方法可執行版本解析 (A 依附 BCBC 都依附不同版本的 D)。

由於 WORKSPACE 有缺點,Bzlmod 將在日後的 Bazel 版本中取代舊版 WORKSPACE 系統。請參閱 Bzlmod 遷移指南,瞭解如何遷移至 Bzlmod。