Bazel 中的 Lockfile 功能可以記錄專案所需的特定版本或依附元件,或是軟體程式庫或套件的依附元件。為達到這個目標,系統會儲存模組解析度和擴充功能評估結果。Lockfile 能夠推動可重現的建構,以確保一致的開發環境。此外,在專案依附元件沒有變更時,Bazel 也會允許 Bazel 略過解析程序,藉此提升建構效率。此外,Lockfile 會防止外部程式庫發生非預期的更新或破壞性變更,從而降低出現錯誤的風險,進而改善穩定性。
產生鎖定檔案
系統會在工作區根目錄下建立名為 MODULE.bazel.lock
的 Lock 檔案。會在建構程序中建立或更新,特別是在模組解析度和擴充功能評估後。Lockfile 會擷取專案目前的狀態,包括 MODULE 檔案、旗標、覆寫值和其他相關資訊。重要的是,這個類別僅包含目前建構作業中包含的依附元件。
如果專案發生變更,且影響其依附元件,Lockfile 會自動更新以反映新狀態。這可確保 Lock 檔案能專注於目前版本所需的特定依附元件組合,以準確呈現專案已解析依附元件。
鎖定檔案使用
如有需要,您可以使用標記 --lockfile_mode
控管 Lock 檔案,以便在專案狀態與鎖定檔案不同時自訂 Bazel 的行為。可用的模式如下:
update
(預設):如果專案狀態與 Lockfile 相符,系統會立即從 Lockfile 傳回解析結果。否則系統會執行解析,並更新 Lockfile 以反映目前狀態。error
:如果專案狀態與 Lockfile 相符,就會從 Lockfile 傳回解析度結果。否則,Bazel 會擲回錯誤,指出專案與 Lockfile 之間的差異。如要確保專案的依附元件維持不變,並將任何差異視為錯誤,這個模式就特別實用。off
:完全未檢查鎖定檔案。
鎖定檔案的優點
這個 Lockfile 的優點如下:
可重現的建構內容。鎖定檔案會擷取軟體程式庫的特定版本或依附元件,確保其版本能在不同的環境和一段時間內重現。開發人員在建構專案時,可以依賴一致且可預測的結果。
有效略過解析度如果專案依附元件自上次建構後沒有任何變更,Lockfile 即可略過解析程序。這可大幅提升建構效率,特別是在解決方案可能相當耗時的情況下。
穩定性與風險降低。並能防止外部程式庫發生非預期的更新或破壞性變更,協助維持穩定性。將依附元件鎖定在特定版本後,就能降低因不相容或未經測試更新而產生錯誤的風險。
鎖定檔案內容
Lockfile 內含所有必要資訊,可判斷專案狀態是否已變更。這也包括以目前狀態建構專案的結果。Lockfile 由兩個主要部分組成:
- 模組解析度的輸入內容,例如
moduleFileHash
、flags
和localOverrideHashes
,以及解析度的輸出內容 (moduleDepGraph
)。 - 針對每個模組擴充功能,Lockfile 包含影響它的輸入內容 (以
transitiveDigest
表示),以及執行該擴充功能的輸出內容 (稱為generatedRepoSpecs
)
以下範例說明 Lockfile 的結構,以及每個區段的說明:
{
"lockFileVersion": 1,
"moduleFileHash": "b0f47b98a67ee15f9.......8dff8721c66b721e370",
"flags": {
"cmdRegistries": [
"https://bcr.bazel.build/"
],
"cmdModuleOverrides": {},
"allowedYankedVersions": [],
"envVarAllowedYankedVersions": "",
"ignoreDevDependency": false,
"directDependenciesMode": "WARNING",
"compatibilityMode": "ERROR"
},
"localOverrideHashes": {
"bazel_tools": "b5ae1fa37632140aff8.......15c6fe84a1231d6af9"
},
"moduleDepGraph": {
"<root>": {
"name": "",
"version": "",
"executionPlatformsToRegister": [],
"toolchainsToRegister": [],
"extensionUsages": [
{
"extensionBzlFile": "extension.bzl",
"extensionName": "lockfile_ext"
}
],
...
}
},
"moduleExtensions": {
"//:extension.bzl%lockfile_ext": {
"general": {
"transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
"generatedRepoSpecs": {
"hello": {
"bzlFile": "@@//:extension.bzl",
...
}
}
}
},
"//:extension.bzl%lockfile_ext2": {
"os:macos": {
"transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=",
"generatedRepoSpecs": {
"hello": {
"bzlFile": "@@//:extension.bzl",
...
}
}
},
"os:linux": {
"transitiveDigest": "eWDzxG/aLsyY3Ubrto....+Jp4maQvEPxn0pLK=",
"generatedRepoSpecs": {
"hello": {
"bzlFile": "@@//:extension.bzl",
...
}
}
}
}
}
}
模組檔案雜湊
moduleFileHash
代表 MODULE.bazel
檔案內容的雜湊。如果這個檔案發生任何變更,雜湊值會有所不同。
旗幟
Flags
物件會儲存可能影響解析度結果的所有標記。
本機覆寫雜湊
如果根模組包含 local_path_overrides
,本節會將 MODULE.bazel
檔案的雜湊儲存在本機存放區中。可讓您追蹤這項依附元件的變更。
模組依附元件圖表
moduleDepGraph
代表使用上述輸入進行解決程序的結果。這會形成執行專案所需的所有模組的依附元件圖表。
模組擴充功能
moduleExtensions
區段是地圖,只包含目前叫用或先前叫用的擴充功能,但不包含任何不再使用的擴充功能。換句話說,如果依附元件圖表不再使用某個擴充功能,系統就會將其從 moduleExtensions
地圖中移除。
如果某個擴充功能與作業系統或架構類型無關,則這個部分只會提供單一「一般」項目。否則,我們會納入多個項目,並以 OS 和/或架構命名,每個項目都會對應至根據這些具體評估擴充功能的結果。
擴充功能對應中的每個項目都對應一種使用的副檔名,並以包含的檔案和名稱來識別。每個項目的對應值都包含與該擴充功能相關聯的相關資訊:
transitiveDigest
是擴充功能實作及其遞移 .bzl 檔案的摘要。- 使用目前輸入內容執行該擴充功能的結果
generatedRepoSpecs
。
另一個可能影響擴充功能結果的因素是其使用方式。雖然未儲存在鎖定檔案中,但當您比較擴充功能目前狀態與鎖定檔案中的擴充功能時,會將這些使用情形納入考量。
最佳做法
為了充分發揮鎖定檔案功能的優勢,請考慮下列最佳做法:
定期更新 Lockfile,以反映專案依附元件或設定的變更。這可確保後續的建構作業都是以最新且正確的一組依附元件為基礎。
將鎖定檔案納入版本控制中,以促進協同合作,並確保所有團隊成員都存取同一個鎖定檔案,在專案中推動一致的開發環境。
使用
bazelisk
執行 Bazel,並在版本控制中納入.bazelversion
檔案,指定與 Lock 檔案對應的 Bazel 版本。由於 Bazel 本身是建構作業的依附元件,因此 Lockfile 專屬於 Bazel 版本,而且會在回溯相容 Bazel 版本之間變更。使用bazelisk
可確保所有開發人員使用的 Bazel 版本與 Lockfile 相符。
只要按照這些最佳做法操作,即可有效使用 Bazel 中的 Lockfile 功能,實現更有效、可靠且協作的軟體開發工作流程。