Di chuyển từ Maven sang Bazel

Báo cáo sự cố Xem nguồn

Trang này mô tả cách di chuyển từ Maven sang Bazel, bao gồm cả các điều kiện tiên quyết và các bước cài đặt. Bài viết này mô tả sự khác biệt giữa Maven và Bazel, đồng thời cung cấp một ví dụ di chuyển bằng cách sử dụng dự án Guava.

Khi di chuyển từ bất kỳ công cụ xây dựng nào sang Bazel, tốt nhất là bạn nên chạy song song cả hai công cụ xây dựng cho đến khi bạn di chuyển hết nhóm phát triển, hệ thống CI và mọi hệ thống có liên quan khác. Bạn có thể chạy Maven và Bazel trong cùng một kho lưu trữ.

Trước khi bắt đầu

  • Cài đặt Bazel nếu bạn chưa cài đặt.
  • Nếu bạn mới sử dụng Bazel, hãy xem hướng dẫn Giới thiệu về Bazel: Xây dựng Java trước khi bắt đầu di chuyển. Phần hướng dẫn này sẽ giải thích các khái niệm, cấu trúc và cú pháp nhãn của Bazel.

Sự khác biệt giữa Maven và Bazel

  • Maven sử dụng(các) tệp pom.xml cấp cao nhất. Bazel hỗ trợ nhiều tệp bản dựng và nhiều mục tiêu trên mỗi tệp BUILD, cho phép các bản dựng có mức độ gia tăng lớn hơn so với Maven.
  • Maven sẽ chịu trách nhiệm về các bước trong quá trình triển khai. Bazel không tự động hoá quá trình triển khai.
  • Bazel cho phép bạn thể hiện sự phụ thuộc giữa các ngôn ngữ.
  • Khi thêm các phần mới vào dự án, bạn có thể phải thêm các tệp BUILD mới bằng Bazel. Cách tốt nhất là thêm tệp BUILD vào từng gói Java mới.

Di chuyển từ Maven sang Bazel

Dưới đây là các bước mô tả cách di chuyển dự án sang Bazel:

  1. Tạo tệp WORKSPACE
  2. Tạo một tệp BUILD
  3. Tạo thêm tệp BUILD
  4. Tạo bản dựng bằng Bazel

Sau đây là các ví dụ về quá trình di chuyển dự án Guava từ Maven sang Bazel. Dự án Guava được sử dụng là bản phát hành v31.1. Các ví dụ sử dụng Guava không hướng dẫn từng bước trong quá trình di chuyển, nhưng sẽ hiển thị các tệp và nội dung được tạo hoặc thêm theo cách thủ công để di chuyển.

$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1

1. Tạo tệp WORKSPACE

Tạo một tệp có tên WORKSPACE ở thư mục gốc của dự án. Nếu dự án của bạn không có phần phụ thuộc bên ngoài, thì tệp không gian làm việc có thể trống.

Nếu dự án của bạn phụ thuộc vào các tệp hoặc gói không có trong một trong các thư mục của dự án, hãy chỉ định các phần phụ thuộc bên ngoài này trong tệp không gian làm việc. Để tự động liệt kê các phần phụ thuộc bên ngoài cho tệp không gian làm việc, hãy sử dụng rules_jvm_external. Để biết hướng dẫn về cách sử dụng bộ quy tắc này, hãy xem phần README.

Ví dụ về dự án Guava: các phần phụ thuộc bên ngoài

Bạn có thể liệt kê các phần phụ thuộc bên ngoài của dự án Guava bằng bộ quy tắc rules_jvm_external.

Thêm đoạn mã sau vào tệp 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. Tạo một tệp BUILD

Giờ đây, khi đã xác định không gian làm việc và các phần phụ thuộc bên ngoài (nếu có), bạn cần tạo các tệp BUILD để mô tả cách xây dựng dự án. Không giống như Maven chỉ có một tệp pom.xml, Bazel có thể dùng nhiều tệp BUILD để tạo một dự án. Các tệp này chỉ định nhiều mục tiêu bản dựng, cho phép Bazel tạo các bản dựng tăng dần.

Thêm BUILD tệp theo giai đoạn. Hãy bắt đầu bằng cách thêm một tệp BUILD ở thư mục gốc của dự án rồi dùng tệp đó để tạo bản dựng ban đầu bằng Bazel. Sau đó, bạn sẽ tinh chỉnh bản dựng bằng cách thêm nhiều tệp BUILD hơn có các mục tiêu chi tiết hơn.

  1. Trong cùng thư mục với tệp WORKSPACE, hãy tạo một tệp văn bản và đặt tên tệp là BUILD.

  2. Trong tệp BUILD này, hãy sử dụng quy tắc phù hợp để tạo một mục tiêu xây dựng dự án. Dưới đây là một số mẹo hay:

    • Hãy sử dụng quy tắc phù hợp:

      • Để xây dựng dự án bằng một mô-đun Maven duy nhất, hãy sử dụng quy tắc java_library như sau:

        java_library(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
        )
        
      • Để xây dựng dự án có nhiều mô-đun Maven, hãy sử dụng quy tắc java_library như sau:

        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"],
        )
        
      • Để tạo tệp nhị phân, hãy sử dụng quy tắc 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"
        )
        
    • Chỉ định các thuộc tính:

      • name: Đặt một cái tên có ý nghĩa cho mục tiêu. Trong các ví dụ ở trên, mục tiêu được gọi là "mọi thứ".
      • srcs: Sử dụng chế độ xem toàn cầu để liệt kê tất cả các tệp .java trong dự án của bạn.
      • resources: Sử dụng hiệu ứng toàn cảnh để liệt kê tất cả tài nguyên trong dự án của bạn.
      • deps: Bạn cần xác định những phần phụ thuộc bên ngoài mà dự án cần. Ví dụ: nếu bạn đã tạo một danh sách các phần phụ thuộc bên ngoài bằng công cụ generate_workspace, thì các phần phụ thuộc cho java_library sẽ là các thư viện được liệt kê trong macro generated_java_libraries.
    • Hãy xem ví dụ bên dưới về tệp BUILD cấp cao nhất này trong quá trình di chuyển dự án Guava.

  3. Giờ đây, khi bạn đã có tệp BUILD ở thư mục gốc của dự án, hãy tạo dự án để đảm bảo tệp hoạt động tốt. Trên dòng lệnh, trong thư mục không gian làm việc, hãy sử dụng bazel build //:everything để tạo dự án bằng Bazel.

    Dự án này hiện đã được xây dựng thành công với Bazel. Bạn sẽ cần bổ sung thêm tệp BUILD để cho phép tạo các bản dựng tăng dần của dự án.

Ví dụ về dự án Guava: bắt đầu bằng một tệp BUILD

Khi di chuyển dự án Guava sang Bazel, ban đầu, một tệp BUILD sẽ được dùng để tạo toàn bộ dự án. Dưới đây là nội dung của tệp BUILD ban đầu này trong thư mục không gian làm việc:

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. Tạo thêm tệp BUILD (không bắt buộc)

Bazel chỉ hoạt động với một BUILD file, như bạn đã thấy sau khi hoàn tất bản dựng đầu tiên. Bạn vẫn nên cân nhắc chia bản dựng thành các phần nhỏ hơn bằng cách thêm nhiều tệp BUILD hơn với các mục tiêu chi tiết.

Nhiều tệp BUILD có nhiều mục tiêu sẽ tăng độ chi tiết của bản dựng, cho phép:

  • đã tăng số bản dựng tăng dần của dự án,
  • tăng mức thực thi song song của bản dựng,
  • khả năng bảo trì tốt hơn của bản dựng cho người dùng trong tương lai, và
  • kiểm soát chế độ hiển thị các mục tiêu giữa các gói, điều này có thể ngăn chặn các vấn đề như thư viện chứa thông tin triển khai bị rò rỉ vào các API công khai.

Mẹo để thêm các tệp BUILD khác:

  • Bạn có thể bắt đầu bằng cách thêm tệp BUILD vào mỗi gói Java. Bắt đầu với các gói Java có ít phần phụ thuộc nhất và cố gắng tạo các gói có nhiều phần phụ thuộc nhất.
  • Khi bạn thêm tệp BUILD và chỉ định mục tiêu, hãy thêm các mục tiêu mới này vào những phần deps phụ thuộc vào mục tiêu. Xin lưu ý rằng hàm glob() không vượt quá ranh giới của gói. Vì vậy, khi số lượng gói tăng lên, các tệp khớp với glob() sẽ giảm xuống.
  • Bất cứ khi nào bạn thêm tệp BUILD vào thư mục main, hãy đảm bảo rằng bạn thêm tệp BUILD vào thư mục test tương ứng.
  • Hãy chú ý giới hạn chế độ hiển thị đúng cách giữa các gói.
  • Để đơn giản hoá việc khắc phục lỗi trong quá trình thiết lập tệp BUILD, hãy đảm bảo rằng dự án sẽ tiếp tục xây dựng bằng Bazel khi bạn thêm từng tệp bản dựng. Hãy chạy bazel build //... để đảm bảo tất cả mục tiêu của bạn vẫn được tạo.

4. Tạo bằng Bazel

Bạn đã tạo bản dựng bằng Bazel khi thêm các tệp BUILD để xác thực chế độ thiết lập bản dựng.

Khi có các tệp BUILD ở độ chi tiết mong muốn, bạn có thể sử dụng Bazel để tạo tất cả các bản dựng.