從 Maven 遷移至 Bazel

7.3 · 7.2 · 7.1 · 7.0 · 6.5

本頁面說明如何從 Maven 遷移至 Bazel,包括必要條件和安裝步驟。說明 Maven 和 Bazel 之間的差異,並提供使用 Guava 專案的遷移範例。

從任何建構工具遷移至 Bazel 時,最好同時執行兩個建構工具,直到開發團隊、持續整合系統和任何其他相關系統完全遷移為止。您可以在同一個存放區中執行 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:

  1. 建立 MODULE.bazel 檔案
  2. 建立一個 BUILD 檔案
  3. 建立更多 BUILD 檔案
  4. 使用 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 檔案,說明如何建構專案。與 Maven 的 pom.xml 檔案不同,Bazel 可以使用多個 BUILD 檔案建構專案。這些檔案會指定多個建構目標,讓 Bazel 產生增量版本。

分階段新增 BUILD 檔案。請先在專案根目錄新增一個 BUILD 檔案,並使用 Bazel 使用該檔案進行初始建構。接著,您可以新增更多 BUILD 檔案,並加入更精細的目標,以便精進建構作業。

  1. MODULE.bazel 檔案所在的目錄中建立文字檔案,並將其命名為 BUILD

  2. 在這個 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:為目標指定有意義的名稱。在上述範例中,目標稱為「所有內容」。
        • srcs:使用 globbing 列出專案中的所有 .java 檔案。
        • resources:使用 globbing 列出專案中的所有資源。
        • deps:您需要判斷專案需要哪些外部依附元件。
      • 請參考下方 這個頂層 BUILD 檔案的範例,瞭解如何遷移 Guava 專案。

  3. 專案根目錄中已含有 BUILD 檔案,請建構專案,確認專案運作正常。在指令列中,從工作區目錄使用 bazel build //:everything 透過 Bazel 建構專案。

    專案現在已成功使用 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 產生所有版本。