從 Maven 遷移至 Bazel

回報問題 查看原始碼 Nightly · 7.4 . 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. 建立 WORKSPACE 檔案
  2. 建立一個 BUILD 檔案
  3. 建立更多 BUILD 檔案
  4. 使用 Bazel 進行建構

以下範例是從 Maven 遷移至 Bazel 的 Guava 專案。使用的 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:為目標指定有意義的名稱。在上述範例中,目標稱為「所有內容」。
      • 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 產生所有建構作業。