外部依附元件總覽

回報問題 查看來源

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

自 Bazel 6.0 起,您可以透過兩種方式使用 Bazel 管理外部依附元件:用於存放區的傳統 WORKSPACE 系統,以及著重於模組的較新 MODULE.bazel 系統 (程式碼名稱為 Bzlmod,並啟用標記 --enable_bzlmod)。這兩個系統可以搭配使用,但 Bzlmod 會在日後的 Bazel 模組中取代 WORKSPACE 系統{/1 的遷移指南。

本文件先說明 Bazel 中外部依附元件管理的相關概念,然後詳細說明這兩個系統。

概念

存放區

具有 WORKSPACEWORKSPACE.bazel 檔案的目錄,包含要在 Bazel 建構作業中使用的來源檔案。通常只有「存放區」即可縮減。

主要存放區

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

工作區

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

請注意,過去「存放區」和「工作區」的概念已限制;「工作區」一詞經常用於指稱主要存放區,有時也會用來當做「存放區」的同義詞。

標準存放區名稱

存放區可定址的標準名稱。在工作區中,每個存放區都有一個標準名稱。存放區中標準名稱為 canonical_name 的目標,可以透過標籤 @@canonical_name//pac/kage:target 處理 (請注意雙 @)。

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

顯目存放區名稱

存放區名稱可透過其他特定存放區的結構定義定址。這可以視為是存放區的「nickname」:具有標準名稱 michael 的存放區在 alice 存放區中可能會有 mike 的明顯名稱,但在存放區 bob 中可能有 mickey 的明顯名稱。在此情況下,可在 alice 中由 @mike//pac/kage:target 標籤處理 michael 中的目標 (請注意單一 @)。

相反地,這可以理解為「存放區對應」:每個存放區都會維持「apparent repo name」與「標準存放區名稱」的對應關係。

存放區規則

存放區定義的結構定義,用來指示 Bazel 如何具體化存放區。例如,您可以「下載特定網址中的 ZIP 封存檔並解壓縮」,或是「擷取特定 Maven 構件並做為 java_import 目標提供」,或是直接「對本機目錄符號連結」。每個存放區都是透過使用適當數量引數來呼叫存放區規則來定義

如要進一步瞭解如何編寫自己的存放區規則,請參閱存放區規則

目前最常見的存放區規則是 http_archive (從網址下載並擷取封存檔) 和 local_repository (符號連結已是 Bazel 存放區的本機目錄)。

擷取存放區

透過執行相關聯的存放區規則,讓本機磁碟可以使用存放區的動作。工作區中定義的存放區在擷取之前,無法用於本機磁碟。

一般而言,Bazel 只會在需要存放區中的內容而擷取存放區時,才會擷取存放區。如果存放區之前已經擷取過,Bazel 只會在其定義有所變更時重新擷取。

目錄版面配置

擷取到存放區後,即可在輸出基礎的「external」子目錄找到存放區,位置在正規名稱之下。

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

ls $(bazel info output_base)/external/ canonical_name 

使用 Bzlmod 管理外部依附元件

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

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 Central Registry。註冊資料庫提供依附元件的 MODULE.bazel 檔案,可讓 Bazel 在執行版本解析之前,探索整個遞移依附元件圖表。

版本解析之後,每個模組都會選取一個版本,Bazel 會再次查詢登錄檔,藉此瞭解如何為每個模組定義存放區 (在大多數情況下,會使用 http_archive)。

模組也可以指定稱為「標記」的自訂資料部分,系統會在模組解析度後使用模組擴充功能加以運用,藉此定義其他存放區。這些擴充功能的功能與存放區規則類似,因此可以執行檔案 I/O 及傳送網路要求等動作。此外,這些程式庫可讓 Bazel 與其他套件管理系統互動,同時遵循 Bazel 模組建構的依附元件圖。

使用 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 系統推出後的幾年內,使用者回報了許多問題點,包括:

  • Bazel 不會評估任何依附元件的 WORKSPACE 檔案,因此除了直接依附元件之外,您必須在主要存放區的 WORKSPACE 檔案中定義所有遞移依附元件。
  • 為解決此問題,專案會採用「deps.bzl」模式,其中定義了一個巨集,並藉此定義多個存放區,並要求使用者在 WORKSPACE 檔案中呼叫這個巨集。
    • 這有其問題:巨集無法 load 其他 .bzl 檔案,因此這些專案必須在這個「deps」巨集中定義遞移依附元件,或是讓使用者呼叫多個分層的「deps」巨集來解決這個問題。
    • Bazel 會依序評估 WORKSPACE 檔案。此外,使用 http_archive 指定依附元件時,不要使用任何版本資訊。這表示在鑽石依附元件的情況下,無法穩定執行版本解析作業 (A 取決於 BCBC 均依附於不同版本的 D)。

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