從 Maven 遷移至 Bazel

回報問題 查看原始碼 Nightly · 8.0 . 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

事前準備

  • 如果尚未安裝 Bazel,請安裝 Bazel
  • 如果您是 Bazel 新手,請先完成教學課程「Bazel 簡介:建構 Java」,再開始遷移作業。本教學課程將說明 Bazel 的概念、結構和標籤語法。

Maven 和 Bazel 的差異

  • Maven 會使用頂層 pom.xml 檔案。Bazel 支援每個 BUILD 檔案的多個建構檔案和多個目標,可讓建構作業比 Maven 更具增量性。
  • Maven 會負責部署程序的步驟。Bazel 不會自動部署。
  • Bazel 可讓您表達不同語言之間的依附元件。
  • 在專案中新增新部分時,您可能需要使用 Bazel 新增新的 BUILD 檔案。最佳做法是將 BUILD 檔案新增至每個新的 Java 套件。

從 Maven 遷移至 Bazel

以下步驟說明如何將專案遷移至 Bazel:

  1. 建立 WORKSPACE 檔案
  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. 建立 WORKSPACE 檔案

在專案的根目錄中建立名為 WORKSPACE 的檔案。如果專案沒有外部依附元件,工作區檔案可以是空白。

如果您的專案依附的檔案或套件不在專案的其中一個目錄中,請在工作區檔案中指定這些外部依附元件。如要自動列出工作區檔案的外部依附元件,請使用 rules_jvm_external。如要瞭解如何使用這個規則集,請參閱 README

Guava 專案範例:外部依附元件

您可以使用 rules_jvm_external 規則集,列出 Guava 專案的外部相依項目。

WORKSPACE 檔案中新增下列程式碼片段:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_JVM_EXTERNAL_TAG = "4.3"
RULES_JVM_EXTERNAL_SHA = "6274687f6fc5783b589f56a2f1ed60de3ce1f99bc4e8f9edef3de43bdf7c6e74"

http_archive(
    name = "rules_jvm_external",
    sha256 = RULES_JVM_EXTERNAL_SHA,
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

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",
    ],
)

2. 建立一個 BUILD 檔案

定義工作區並列出外部依附元件 (如適用) 後,您需要建立 BUILD 檔案,說明專案應如何建構。與 Maven 的單一 pom.xml 檔案不同,Bazel 可使用多個 BUILD 檔案建構專案。這些檔案會指定多個建構目標,讓 Bazel 產生增量版本。

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

  1. WORKSPACE 檔案所在的目錄中,建立文字檔案並將其命名為 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:為目標指定有意義的名稱。在上述範例中,目標稱為「everything」。
      • srcs:使用 globbing 列出專案中的所有 .java 檔案。
      • resources:使用 globbing 列出專案中的所有資源。
      • deps:您需要判斷專案需要哪些外部依附元件。舉例來說,如果您使用 generate_workspace 工具產生外部依附元件清單,java_library 的依附元件就是 generated_java_libraries 巨集中列出的程式庫。
    • 請參閱 Guava 專案遷移作業中以下這個頂層 BUILD 檔案的範例

  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",
    ]),
    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 產生所有建構項目。