由於 WORKSPACE,Bzlmod 會 在日後的 Bazel 版本中,取代舊版 WORKSPACE 系統這份指南 您將專案遷移至 Bzlmod 並捨棄 WORKSPACE 以擷取外部 依附元件
WORKSPACE 與 Bzlmod
Bazel 的 WORKSPACE 與 Bzlmod 提供了語法不同的類似功能。這個 本節說明如何從特定 WORKSPACE 功能遷移至 Bzlmod。
定義 Bazel 工作區的根
WORKSPACE 檔案會標示 Bazel 專案的來源根目錄 (此責任)
在 Bazel 6.3 以上版本中,已由 MODULE.bazel 取代。使用 Bazel 版本
6.3 之前的 WORKSPACE
或 WORKSPACE.bazel
檔案,在
至於工作區根層級,您可以使用下列註解:
工作區
# This file marks the root of the Bazel workspace. # See MODULE.bazel for external dependencies setup.
在 bazelrc 中啟用 Bzlmod
.bazelrc
可讓您設定每次執行 Bazel 時都適用的標記。啟用方式
Bzlmod,使用 --enable_bzlmod
旗標,並將其套用至 common
指令,因此
適用於所有指令:
.bazelrc
# Enable Bzlmod for every Bazel command common --enable_bzlmod
指定工作區的存放區名稱
工作區
使用
workspace
函式 為工作區指定存放區名稱。這使 以「@<workspace name>//foo:bar
」的形式參照工作區的「//foo:bar
」。如未指定,您的預設存放區名稱 工作區為「__main__
」。## WORKSPACE workspace(name = "com_foo_bar")
Bzlmod
建議您在含有 不含
@<repo name>
的//foo:bar
語法。不過,如果您需要使用舊版語法 ,您可以使用由module
函式做為存放區 名稱。如果模組名稱與所需存放區名稱不同, 可以使用repo_name
屬性的module
函式用來覆寫 存放區名稱## MODULE.bazel module( name = "bar", repo_name = "com_foo_bar", )
以 Bazel 模組擷取外部依附元件
如果您的依附元件是 Bazel 專案,應該就能以 Bazel 模組,前提是該模組也採用 Bzlmod。
工作區
使用 WORKSPACE 時,通常會使用
http_archive
或git_repository
存放區規則 下載 Bazel 專案的來源## WORKSPACE load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "bazel_skylib", urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.4.2/bazel-skylib-1.4.2.tar.gz"], sha256 = "66ffd9315665bfaafc96b52278f57c7e2dd09f5ede279ea6d39b2be471e7e3aa", ) load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() http_archive( name = "rules_java", urls = ["https://github.com/bazelbuild/rules_java/releases/download/6.1.1/rules_java-6.1.1.tar.gz"], sha256 = "76402a50ae6859d50bd7aed8c1b8ef09dae5c1035bb3ca7d276f7f3ce659818a", ) load("@rules_java//java:repositories.bzl", "rules_java_dependencies", "rules_java_toolchains") rules_java_dependencies() rules_java_toolchains()
如您所見,使用者經常需要 依附元件巨集中的依附元件。假設
bazel_skylib
和rules_java
依附於platform
,也就是platform
的確切版本 依附元件是由巨集的順序決定。Bzlmod
使用 Bzlmod (前提是您的依附元件可在 Bazel Central 中提供) 登錄檔或自訂 Bazel 註冊資料庫後
bazel_dep
指令。## MODULE.bazel bazel_dep(name = "bazel_skylib", version = "1.4.2") bazel_dep(name = "rules_java", version = "6.1.1")
Bzlmod 會使用 MVS 演算法。因此,最大值 系統會自動選取
platform
的必要版本。
將依附元件覆寫為 Bazel 模組
由於是根模組,您可以覆寫不同位置的 Bazel 模組依附元件 管理基礎架構
詳情請參閱「覆寫」一節 可能不準確或不適當
您可以在 例子 Cloud Storage 也提供目錄同步處理功能
使用模組擴充功能擷取外部依附元件
如果依附元件並非 Bazel 專案,或尚未在任何 Bazel 中使用
就能使用
use_repo_rule
或 module
擴充功能。
工作區
使用
http_file
下載檔案 存放區規則## WORKSPACE load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") http_file( name = "data_file", url = "http://example.com/file", sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", )
Bzlmod
透過 Bzlmod,您可以在 MODULE.bazel 中使用
use_repo_rule
指令 檔案,直接對存放區執行個體化:## MODULE.bazel http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") http_file( name = "data_file", url = "http://example.com/file", sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", )
基本上,這是透過模組擴充功能實作。如果需要 可執行更複雜的邏輯,而不只是叫用存放區規則。 自行實作模組擴充功能請移動定義 轉換為
.bzl
檔案,後者可讓您共用 在遷移期間使用 WORKSPACE 和 Bzlmod。## repositories.bzl load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") def my_data_dependency(): http_file( name = "data_file", url = "http://example.com/file", sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", )
實作模組擴充功能,載入依附元件巨集。您可以定義 這個巨集位於巨集的同一個
.bzl
檔案中,但是為了與 建議您建立另一個.bzl
檔案。## extensions.bzl load("//:repositories.bzl", "my_data_dependency") def _non_module_dependencies_impl(_ctx): my_data_dependency() non_module_dependencies = module_extension( implementation = _non_module_dependencies_impl, )
如要讓根專案查看存放區,請宣告 模組擴充功能和 MODULE.bazel 檔案中存放區的用法。
## MODULE.bazel non_module_dependencies = use_extension("//:extensions.bzl", "non_module_dependencies") use_repo(non_module_dependencies, "data_file")
使用模組擴充功能解決衝突的外部依附元件
專案可提供根據 呼叫其呼叫端但如果 是否會造成衝突?
假設專案 foo
提供下列巨集,將 version
做為
引數。
## repositories.bzl in foo {:#repositories.bzl-foo}
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
def data_deps(version = "1.0"):
http_file(
name = "data_file",
url = "http://example.com/file-%s" % version,
# Omitting the "sha256" attribute for simplicity
)
工作區
使用 WORKSPACE 時,您可以從
@foo
載入巨集並指定版本 所需的資料依附元件假設您還有另一個依附元件@bar
這也取決於@foo
,但需要其他版本的資料 依附元件## WORKSPACE # Introduce @foo and @bar. ... load("@foo//:repositories.bzl", "data_deps") data_deps(version = "2.0") load("@bar//:repositories.bzl", "bar_deps") bar_deps() # -> which calls data_deps(version = "3.0")
在此情況下,使用者必須謹慎調整 WORKSPACE 檔案取得所需版本。這是最艱鉅的任務之一 使用 WORKSPACE 模型,因為這個方法無法提供有效的方式 解析依附元件
Bzlmod
透過 Bzlmod,專案
foo
的作者可以使用模組擴充功能來解決問題 衝突。舉例來說,假設一律選取 所有 Bazel 模組的資料依附元件最低版本需求。## extensions.bzl in foo load("//:repositories.bzl", "data_deps") data = tag_class(attrs={"version": attr.string()}) def _data_deps_extension_impl(module_ctx): # Select the maximal required version in the dependency graph. version = "1.0" for mod in module_ctx.modules: for data in mod.tags.data: version = max(version, data.version) data_deps(version) data_deps_extension = module_extension( implementation = _data_deps_extension_impl, tag_classes = {"data": data}, )
## MODULE.bazel in bar bazel_dep(name = "foo", version = "1.0") foo_data_deps = use_extension("@foo//:extensions.bzl", "data_deps_extension") foo_data_deps.data(version = "3.0") use_repo(foo_data_deps, "data_file")
## MODULE.bazel in root module bazel_dep(name = "foo", version = "1.0") bazel_dep(name = "bar", version = "1.0") foo_data_deps = use_extension("@foo//:extensions.bzl", "data_deps_extension") foo_data_deps.data(version = "2.0") use_repo(foo_data_deps, "data_file")
在此情況下,根模組需要資料版本
2.0
, 依附元件bar
需要3.0
。foo
中的模組擴充功能可正確 解決這項衝突,並自動為資料選取「3.0
」版本 依附元件
整合第三方套件管理工具
延續上一節的內容,因為模組擴充功能可讓您收集 ,執行自訂邏輯來解決問題 找出外部存放區的依附元件和呼叫存放區規則 可讓規則作者輕鬆強化將 特定語言的套件管理工具
詳情請參閱「模組擴充功能」頁面 如何使用模組擴充功能
以下是已採用 Bzlmod 擷取依附元件的規則集清單 不同的套件管理工具:
如要整合虛擬套件管理員,請參閱這個最精簡的範例 例子 Cloud Storage 也提供目錄同步處理功能
偵測主機上的工具鍊
當 Bazel 建構規則需要偵測主機上可用的工具鍊時 就會使用存放區規則來檢查主體機器 工具鍊資訊做為外部存放區使用
工作區
以下列存放區規則偵測殼層工具鍊。
## local_config_sh.bzl def _sh_config_rule_impl(repository_ctx): sh_path = get_sh_path_from_env("SH_BIN_PATH") if not sh_path: sh_path = detect_sh_from_path() if not sh_path: sh_path = "/shell/binary/not/found" repository_ctx.file("BUILD", """ load("@bazel_tools//tools/sh:sh_toolchain.bzl", "sh_toolchain") sh_toolchain( name = "local_sh", path = "{sh_path}", visibility = ["//visibility:public"], ) toolchain( name = "local_sh_toolchain", toolchain = ":local_sh", toolchain_type = "@bazel_tools//tools/sh:toolchain_type", ) """.format(sh_path = sh_path)) sh_config_rule = repository_rule( environ = ["SH_BIN_PATH"], local = True, implementation = _sh_config_rule_impl, )
您可以在 WORKSPACE 中載入存放區規則。
## WORKSPACE load("//:local_config_sh.bzl", "sh_config_rule") sh_config_rule(name = "local_config_sh")
Bzlmod
透過 Bzlmod,您可以使用模組擴充功能來導入相同的存放區。 這類似於上次介紹
@data_file
存放區的情況 專區。## local_config_sh_extension.bzl load("//:local_config_sh.bzl", "sh_config_rule") sh_config_extension = module_extension( implementation = lambda ctx: sh_config_rule(name = "local_config_sh"), )
然後在 MODULE.bazel 檔案中使用擴充功能。
## MODULE.bazel sh_config_ext = use_extension("//:local_config_sh_extension.bzl", "sh_config_extension") use_repo(sh_config_ext, "local_config_sh")
註冊工具鍊和執行平台
按照上一節的說明,介紹存放區代管工具鍊後
資訊 (例如:local_config_sh
) 時,建議您註冊
工具鍊。
工作區
使用 WORKSPACE 時,您可以透過以下方式註冊工具鍊。
您可以在
.bzl
檔案中註冊工具鍊,並在 WORKSPACE 檔案。## local_config_sh.bzl def sh_configure(): sh_config_rule(name = "local_config_sh") native.register_toolchains("@local_config_sh//:local_sh_toolchain")
## WORKSPACE load("//:local_config_sh.bzl", "sh_configure") sh_configure()
您也可以直接在 WORKSPACE 檔案中註冊工具鍊。
## WORKSPACE load("//:local_config_sh.bzl", "sh_config_rule") sh_config_rule(name = "local_config_sh") register_toolchains("@local_config_sh//:local_sh_toolchain")
Bzlmod
採用 Bzlmod 的
register_toolchains
和register_execution_platforms
。 只有 MODULE.bazel 檔案提供 API。你無法撥打電話 模組擴充功能中的native.register_toolchains
。## MODULE.bazel sh_config_ext = use_extension("//:local_config_sh_extension.bzl", "sh_config_extension") use_repo(sh_config_ext, "local_config_sh") register_toolchains("@local_config_sh//:local_sh_toolchain")
在 WORKSPACE
中註冊的工具鍊和執行平台,
WORKSPACE.bzlmod
和每個 Bazel 模組的 MODULE.bazel
檔案都會遵循以下程式碼
工具鍊選取作業期間的優先順序 (由高至低):
- 在根模組
MODULE.bazel
檔案。 - 工具鍊和執行平台,註冊於
WORKSPACE
或WORKSPACE.bzlmod
檔案。 - 工具鍊和執行平台,由開發人員 根模組的 (遞移) 依附元件。
- 不使用
WORKSPACE.bzlmod
時:在WORKSPACE
中註冊的工具鍊 後置字串。
導入本機存放區
您需要將依附元件導入為本機存放區時 依附元件的本機版本,或是想將 做為外部存放區
工作區
使用 WORKSPACE 時,這項作業是由兩個原生存放區規則來完成
local_repository
和new_local_repository
。## WORKSPACE local_repository( name = "rules_java", path = "/Users/bazel_user/workspace/rules_java", )
Bzlmod
採用 Bzlmod 設計
local_path_override
到 使用本機路徑覆寫模組。## MODULE.bazel bazel_dep(name = "rules_java") local_path_override( module_name = "rules_java", path = "/Users/bazel_user/workspace/rules_java", )
您也能導入包含模組擴充功能的本機存放區。 但是,您無法在模組擴充功能中呼叫
native.local_repository
。 正在持續努力解決所有原生存放區規則的星號 (勾選 #18285 代表進度)。 然後您可以在模組中呼叫對應的星線local_repository
。實作自訂版本的local_repository
存放區規則 (如果這是您遇到的阻礙問題)。
繫結目標
WORKSPACE 中的 bind
規則已淘汰,
Bzlmod 不支援範本。它在 YAML 檔案中為目標命名
特殊的 //external
套件。系統會遷移所有相關使用者。
舉例來說
## WORKSPACE
bind(
name = "openssl",
actual = "@my-ssl//src:openssl-lib",
)
這可讓其他目標依附於 //external:openssl
。您可以遷移
應採取的因應措施:
將
//external:openssl
的所有用法取代為@my-ssl//src:openssl-lib
。或使用
alias
建構規則在套件中定義下列目標 (例如
//third_party
)## third_party/BUILD alias( name = "openssl", actual = "@my-ssl//src:openssl-lib", )
將
//external:openssl
的所有用法取代為//third_party:openssl
。
擷取與同步處理
擷取和同步指令的用途是下載外部存放區並保留在本機
已更新有時候,您也可以透過 --nofetch
允許離線建構
標記。
工作區
同步處理功能會針對所有存放區或特定 而擷取資源則「只」用於擷取 目標。
Bzlmod
同步處理指令已不適用,但擷取優惠 各種選項。 您可以擷取目標、存放區、一組已設定的存放區,或全部 依附元件解析和模組擴充功能涉及的存放區。 系統會快取擷取結果,並強制擷取結果,您必須在其中加入
--force
選項。
遷移
本節提供 Bzlmod 遷移作業的實用資訊和指引 上傳資料集之後,您可以運用 AutoML 自動完成部分資料準備工作
瞭解 WORKSPACE 中的依附元件
遷移的第一步是瞭解您有哪些依附元件。這項服務
可能難以識別
WORKSPACE 檔案,因為遞移依附元件通常會透過 *_deps
載入
巨集。
使用工作區解析的檔案檢查外部依附元件
幸運的是
--experimental_repository_resolved_file
敬上
可以幫助他們達成目標這個標記基本上會產生一個「鎖定檔案」佔所有已擷取外部
套用至最後一個 Bazel 指令的依附元件詳情請參閱這篇網誌文章
文章。
使用方法有兩種:
擷取建構特定目標所需的外部依附元件資訊。
bazel clean --expunge bazel build --nobuild --experimental_repository_resolved_file=resolved.bzl //foo:bar
擷取 WORKSPACE 檔案中定義的所有外部依附元件的資訊。
bazel clean --expunge bazel sync --experimental_repository_resolved_file=resolved.bzl
透過
bazel sync
指令,您可以擷取 WORKSPACE 檔案,包括:bind
個用量register_toolchains
和register_execution_platforms
個用量
不過,如果您的專案是跨平台,則 bazel 同步處理作業可能會在特定 因為某些存放區規則只能在支援的裝置上 平台。
執行指令後,您應該會發現
resolved.bzl
檔案中的依附元件。
使用 bazel query
檢查外部依附元件
您可能也會知道 bazel query
可用於檢查存放區規則
bazel query --output=build //external:<repo name>
雖然 bazel 查詢比以前更方便也快速,但 外部依附元件版本 所以務必要謹慎使用查詢及檢查外部 將以 Bzlmod 的依附元件來說, 子指令。
內建預設依附元件
檢查 --experimental_repository_resolved_file
產生的檔案之後
您會找出許多未在 WORKSPACE 中定義的依附元件。
這是因為 Bazel 實際上會為使用者的 WORKSPACE 新增前置字串和後置字串
檔案內容插入一些預設依附性,這類依附元件通常
原生規則 (例如 @bazel_tools
、@platforms
和 @remote_java_tools
)。取代為
Bzlmod,這些依附元件是透過內建模組導入
bazel_tools
,這是其他各方的預設依附元件
Bazel 模組。
逐步遷移的混合模式
Bzlmod 和 WORKSPACE 可同時運作,以便遷移依附元件 從 WORKSPACE 檔案指向 Bzlmod 為逐步程序。
WORKSPACE.bzlmod
在遷移期間,Bazel 使用者可能需要 未啟用 Bzlmod。實作 WORKSPACE.bzlmod 支援, 讓處理程序更加順暢
WORKSPACE.bzlmod 的語法與 WORKSPACE 相同。啟用 Bzlmod 時 如果工作區根目錄中也有 WORKSPACE.bzlmod 檔案:
WORKSPACE.bzlmod
將生效,系統會忽略WORKSPACE
的內容。- 沒有任何前置字串或後置字串 已新增至 WORKSPACE.bzlmod 檔案。
使用 WORKSPACE.bzlmod 檔案可協助您簡化遷移作業,原因如下:
- Bzlmod 停用後,就會改回從 原始的 WORKSPACE 檔案
- 啟用 Bzlmod 時,您可以更妥善地追蹤剩下哪些依附元件 使用 WORKSPACE.bzlmod 遷移。
存放區瀏覽權限
Bzlmod 可以控制來自指定資源的其他存放區 查看存放區名稱與嚴格存放區 deps。
以下摘要說明不同類型的存放區瀏覽權限 容器也需一併考量
從主要存放區 | 來自 Bazel 模組存放區 | 來自模組擴充功能存放區 | 來自 WORKSPACE 存放區 | |
---|---|---|---|---|
主要存放區 | 顯示 | 如果根模組為直接依附元件 | 如果根模組是代管模組擴充功能的模組直接依附元件 | 顯示 |
Bazel 模組存放區 | 直接依附元件 | 直接依附元件 | 代管模組擴充功能的模組直接依附元件 | 直接模組的依附元件 |
模組擴充功能存放區 | 直接依附元件 | 直接依附元件 | 代管模組擴充功能的模組直接依附元件 + 由相同模組擴充功能產生的所有存放區 | 直接模組的依附元件 |
Workspace 重寫 | 所有可見項目 | 隱藏 | 隱藏 | 所有可見項目 |
遷移程序
典型的 Bzlmod 遷移程序如下:
- 瞭解 WORKSPACE 中的依附元件。
- 在專案根目錄中新增空白的 MODULE.bazel 檔案。
- 新增空白的 WORKSPACE.bzlmod 檔案,以覆寫 WORKSPACE 檔案內容。
- 在啟用 Bzlmod 的情況下建構目標,並檢查哪個存放區
- 檢查已解析依附元件中缺少存放區的定義 檔案。
- 透過模組將缺少的依附元件導入為 Bazel 模組 也可以將其保留在 WORKSPACE.bzlmod 中,以便稍後遷移。
- 請返回第 4 項,然後重複執行,直到所有依附元件都可用為止。
遷移工具
我們提供互動式 Bzlmod 遷移輔助指令碼, 即可開始使用
這個指令碼會執行下列作業:
- 產生並剖析 WORKSPACE 解析的檔案。
- 以使用者可理解的方式列印已解析檔案中的存放區資訊。
- 執行 bazel 建構指令、偵測辨識出的錯誤訊息,以及建議 讓您以不同方式進行遷移
- 檢查 BCR 中是否已有依附元件。
- 將依附元件新增至 MODULE.bazel 檔案。
- 透過模組擴充功能新增依附元件。
- 將依附元件新增至 WORKSPACE.bzlmod 檔案。
如要使用,請確認您的應用程式已安裝最新的 Bazel 版本,並執行 以下指令:
git clone https://github.com/bazelbuild/bazel-central-registry.git
cd <your workspace root>
<BCR repo root>/tools/migrate_to_bzlmod.py -t <your build targets>
發布 Bazel 模組
如果您的 Bazel 專案是其他專案的依附元件 Bazel Central Registry 中所含的專案。
如要在 BCR 中查看專案,您必須將來源封存網址設為 專案。建立來源封存檔時,請注意下列事項:
確認封存檔指向特定版本。
BCR 只接受版本化來源封存檔,因為 Bzlmod 必須 在依附元件解析期間比較版本。
確保封存網址穩定。
Bazel 會根據雜湊值驗證封存的內容,因此您應 確認下載檔案的總和檢查碼一律不會變更。如果網址為 ,請在發布頁面中建立並上傳版本封存檔。 GitHub 不保證一定能針對以下項目產生的來源封存檔總和檢查碼: 需求量。簡單來說,網址形式為 將「
https://github.com/<org>/<repo>/releases/download/...
」視為穩定版 而https://github.com/<org>/<repo>/archive/...
則不是。檢查 GitHub 封存總和檢查碼 服務中斷 瞭解背景資訊。確認來源樹狀結構符合原始存放區的版面配置。
如果存放區相當龐大,而您打算建立發布版本 清除不必要的來源,縮減檔案大小,請 確定移除的來源樹狀結構是原始來源樹狀結構的子集。這個 方便使用者將模組覆寫為非發布 版本:
archive_override
和git_override
。在可測試常用項目的子目錄中納入測試模組 API 整合
測試模組是具有專屬 WORKSPACE 和 MODULE.bazel 的 Bazel 專案 檔案位於來源封存檔的子目錄中,會根據 實際發布的模組其中應包含範例或 整合測試,涵蓋最常見的 API。確認 測試模組瞭解設定方式。
準備好來源封存網址後,請追蹤 BCR 貢獻內容 指南,即可透過 GitHub 將模組提交至 BCR 提取要求。
強烈建議設定發布到 BCR GitHub 應用程式,適用於 ,將模組提交至 BCR。
最佳做法
本節將說明幾項您應遵循的最佳做法。 管理外部依附元件
將目標分割成不同套件,避免擷取不必要的依附元件。
勾選 #12835,開發位置 系統將強制擷取測試依附元件,藉此進行建構 不需要這些類別的物件這並非 Bzlmod 具體, 遵循上述做法,您就能更輕鬆地正確指定開發依附元件。
指定開發依附元件
您可以將 dev_dependency
屬性設為 true
bazel_dep
和
use_extension
指令,
但不會套用至相依專案根模組可以使用
--ignore_dev_dependency
標記來驗證目標
仍會在沒有開發人員依附元件的情況下建構
社群遷移進度
您可以檢查 Bazel Central Registry 來找出 看看依附元件是否已存在你也可以隨時加入這個行列 GitHub 討論,前往 或發布導致遷移作業阻礙遷移作業的依附元件。
回報問題
請查看 Bazel GitHub 問題清單,確認已知的 Bzlmod 以負載平衡機制分配流量 即可降低應用程式發生效能問題的風險歡迎您提出新的問題或提出新功能要求,以利解除封鎖