本頁面說明如何從 Maven 遷移至 Bazel,包括先決條件和安裝步驟。說明 Maven 和 Bazel 的差異,並提供使用 Guava 專案的遷移範例。
從任何建構工具遷移至 Bazel 時,最好讓這兩種建構工具並行運作,直到開發團隊、CI 系統和任何其他相關系統完全遷移為止。您可以在同一個存放區中執行 Maven 和 Bazel。
事前準備
- 如果尚未安裝 Bazel,請安裝。
- 如果您是 Bazel 新手,請先完成「Bazel 簡介:建構 Java」教學課程,再開始遷移。本教學課程說明 Bazel 的概念、結構和標籤語法。
Maven 和 Bazel 的差異
- Maven 會使用頂層
pom.xml
檔案。Bazel 支援多個建構檔案,以及每個BUILD
檔案的多個目標,因此建構作業比 Maven 更能以累加方式進行。 - Maven 會負責部署程序的步驟。Bazel 不會自動部署。
- 您可以使用 Bazel 表示語言之間的依附元件。
- 在專案中新增區段時,您可能需要使用 Bazel 新增
BUILD
檔案。最佳做法是在每個新的 Java 套件中新增BUILD
檔案。
從 Maven 遷移至 Bazel
以下說明如何將專案遷移至 Bazel:
以下範例來自 Guava 專案從 Maven 遷移至 Bazel 的過程。使用的 Guava 專案是 v31.1
版。使用 Guava 的範例不會逐步說明遷移作業,但會顯示為遷移作業產生或手動新增的檔案和內容。
$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1
1. 建立 MODULE.bazel 檔案
在專案的根目錄中建立名為 MODULE.bazel
的檔案。如果專案沒有外部依附元件,這個檔案可以空白。
如果專案依附於專案目錄以外的檔案或套件,請在 MODULE.bazel 檔案中指定這些外部依附元件。您可以使用 rules_jvm_external
管理 Maven 的依附元件。如需使用這組規則的操作說明,請參閱 README。
Guava 專案範例:外部依附元件
您可以使用 rules_jvm_external
規則集,列出 Guava 專案的外部依附元件。
在 MODULE.bazel
檔案中新增下列程式碼片段:
bazel_dep(name = "rules_jvm_external", version = "6.2")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.j2objc:j2objc-annotations:1.3",
"org.codehaus.mojo:animal-sniffer-annotations:1.20",
"org.checkerframework:checker-qual:3.12.0",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
use_repo(maven, "maven")
2. 建立一個 BUILD 檔案
定義工作區並列出外部依附元件 (如適用) 後,您需要建立 BUILD
檔案,說明專案的建構方式。與只有一個 pom.xml
檔案的 Maven 不同,Bazel 可以使用多個 BUILD
檔案建構專案。這些檔案會指定多個建構目標,讓 Bazel 產生累加建構。
分階段新增 BUILD
檔案。首先,請在專案根目錄中新增一個 BUILD
檔案,並使用該檔案透過 Bazel 進行初始建構。接著,您會新增更多具有更精細目標的 BUILD
檔案,進一步調整建構作業。
在
MODULE.bazel
檔案所在的目錄中,建立文字檔案並將其命名為BUILD
。在這個
BUILD
檔案中,請使用適當的規則建立一個目標,以建構專案。以下提供幾項訣竅:請使用適當的規則:
如要使用單一 Maven 模組建構專案,請使用
java_library
規則,如下所示:java_library( name = "everything", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**"]), deps = ["//:all-external-targets"], )
如要使用多個 Maven 模組建構專案,請使用
java_library
規則,如下所示:java_library( name = "everything", srcs = glob([ "Module1/src/main/java/**/*.java", "Module2/src/main/java/**/*.java", ... ]), resources = glob([ "Module1/src/main/resources/**", "Module2/src/main/resources/**", ... ]), deps = ["//:all-external-targets"], )
如要建構二進位檔,請使用
java_binary
規則:java_binary( name = "everything", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**"]), deps = ["//:all-external-targets"], main_class = "com.example.Main" )
指定屬性:
name
:為目標命名,在上述範例中,目標稱為「everything」。srcs
:使用 globbing 列出專案中的所有 .java 檔案。resources
:使用 globbing 列出專案中的所有資源。deps
:您需要判斷專案需要哪些外部依附元件。
專案根目錄中已有
BUILD
檔案,請建構專案,確保專案正常運作。在指令列中,從工作區目錄使用bazel build //:everything
建構專案。專案現在已使用 Bazel 成功建構。您需要新增更多
BUILD
檔案,才能逐步建構專案。
Guava 專案範例:從一個 BUILD 檔案開始
將 Guava 專案遷移至 Bazel 時,一開始會使用一個 BUILD
檔案建構整個專案。以下是工作區目錄中這個初始 BUILD
檔案的內容:
java_library(
name = "everything",
srcs = glob([
"guava/src/**/*.java",
"futures/failureaccess/src/**/*.java",
]),
javacopts = ["-XepDisableAllChecks"],
deps = [
"@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_j2objc_j2objc_annotations",
"@maven//:org_checkerframework_checker_qual",
"@maven//:org_codehaus_mojo_animal_sniffer_annotations",
],
)
3. 建立更多 BUILD 檔案 (選用)
如您在完成第一次建構後所見,Bazel 只要一個 BUILD file
即可運作。您仍應考慮新增更多具有細微目標的 BUILD
檔案,將建構作業分成較小的區塊。
如果有多個 BUILD
檔案和多個目標,建構作業的精細度就會提高,因此可以:
- 增加專案的累加建構作業,
- 增加建構的平行執行次數,
- 為日後使用者提供更易於維護的建構版本,以及
- 控管套件間目標的可見度,避免程式庫含有實作詳細資料,導致資訊洩漏至公開 API 等問題。
新增更多 BUILD
檔案的提示:
- 您可以先為每個 Java 套件新增
BUILD
檔案。先從依附元件最少的 Java 套件開始,再逐步處理依附元件最多的套件。 - 加入
BUILD
檔案並指定目標後,請將這些新目標新增至依附於這些目標的目標deps
區段。請注意,glob()
函式不會跨越套件界線,因此隨著套件數量增加,glob()
比對的檔案會減少。 - 每當您將
BUILD
檔案新增至main
目錄時,請務必將BUILD
檔案新增至對應的test
目錄。 - 請務必適當限制套件之間的瀏覽權限。
- 為簡化
BUILD
檔案設定中的錯誤疑難排解程序,請確保在新增每個建構檔案時,專案仍可透過 Bazel 建構。執行bazel build //...
,確保所有目標仍可建構。
4. 使用 Bazel 建構
您已使用 Bazel 建構,並將 檔案新增至驗證建構設定。BUILD
當您擁有所需精細程度的 BUILD
檔案時,可以使用 Bazel 產生所有建構作業。