การย้ายข้อมูลจาก Maven ไปยัง Bazel

รายงานปัญหา ดูแหล่งที่มา

หน้านี้อธิบายวิธีย้ายข้อมูลจาก Maven ไปยัง Bazel รวมถึงข้อกำหนดเบื้องต้นและขั้นตอนการติดตั้ง ซึ่งจะอธิบายความแตกต่างระหว่าง Maven และ Bazel ตลอดจนแสดงตัวอย่างการย้ายข้อมูลโดยใช้โปรเจ็กต์ Guava

เมื่อย้ายข้อมูลจากเครื่องมือบิลด์ใดก็ตามไปยัง Bazel ควรเตรียมเครื่องมือบิลด์ทั้งคู่ให้ทำงานพร้อมกันจนกว่าคุณจะย้ายข้อมูลทีมพัฒนา, ระบบ CI และระบบอื่นๆ ที่เกี่ยวข้องอย่างสมบูรณ์ คุณเรียกใช้ Maven และ Bazel ในที่เก็บเดียวกันได้

ก่อนเริ่มต้น

ความแตกต่างระหว่าง Maven และ Bazel

  • Maven ใช้ไฟล์ pom.xml ระดับบนสุด Bazel รองรับไฟล์บิลด์หลายไฟล์และหลายเป้าหมายต่อไฟล์ BUILD ซึ่งช่วยให้สร้างบิลด์ได้มากกว่า Maven
  • Maven จะดูแลขั้นตอนต่างๆ ในกระบวนการทำให้ใช้งานได้ Bazel ไม่ได้ติดตั้งใช้งานโดยอัตโนมัติ
  • Bazel ให้คุณแสดงทรัพยากร Dependency ระหว่างภาษาได้
  • เมื่อเพิ่มส่วนใหม่ในโปรเจ็กต์ คุณอาจต้องเพิ่มไฟล์ BUILD ใหม่เมื่อใช้ Bazel แนวทางปฏิบัติแนะนำคือเพิ่มไฟล์ 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 ที่รูทของโปรเจ็กต์ หากโปรเจ็กต์ไม่มีทรัพยากร Dependency ภายนอก ไฟล์พื้นที่ทำงานจะว่างเปล่าได้

หากโปรเจ็กต์ของคุณใช้ไฟล์หรือแพ็กเกจที่ไม่ได้อยู่ในไดเรกทอรีของโปรเจ็กต์ ให้ระบุทรัพยากร Dependency ภายนอกเหล่านี้ในไฟล์พื้นที่ทำงาน หากต้องการให้แสดงรายการทรัพยากร Dependency ภายนอกสำหรับไฟล์พื้นที่ทำงานโดยอัตโนมัติ ให้ใช้ rules_jvm_external สำหรับคำแนะนำเกี่ยวกับการใช้ชุดกฎนี้ โปรดดู README

ตัวอย่างโปรเจ็กต์ Guava: ทรัพยากร Dependency ภายนอก

คุณแสดงรายการทรัพยากร Dependency ภายนอกของโปรเจ็กต์ Guava ได้ด้วยชุดกฎ rules_jvm_external

เพิ่มข้อมูลโค้ดต่อไปนี้ลงในไฟล์ 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 ไฟล์เดียว

ตอนนี้คุณระบุพื้นที่ทำงานแล้วและทรัพยากร Dependency ภายนอก (หากมี) อยู่ในรายการแล้ว คุณจะต้องสร้างไฟล์ BUILD เพื่ออธิบายวิธีสร้างโปรเจ็กต์ Bazel สามารถใช้ไฟล์จำนวนมาก BUILD เพื่อสร้างโปรเจ็กต์ ซึ่งต่างจาก Maven ที่มีไฟล์ pom.xml เดียว ไฟล์เหล่านี้ระบุเป้าหมายของบิลด์หลายรายการ ซึ่งทำให้ Bazel สร้างบิลด์เพิ่มขึ้นได้

เพิ่ม BUILD ไฟล์ทีละไฟล์ เริ่มต้นด้วยการเพิ่มไฟล์ BUILD 1 ไฟล์ที่รูทของโปรเจ็กต์และใช้เพื่อสร้างบิลด์เริ่มต้นโดยใช้ Bazel จากนั้นปรับแต่งบิลด์ด้วยการเพิ่มไฟล์ BUILD ที่มีเป้าหมายแบบละเอียดขึ้น

  1. ในไดเรกทอรีเดียวกับไฟล์ WORKSPACE ให้สร้างไฟล์ข้อความและตั้งชื่อว่า BUILD

  2. ในไฟล์ BUILD นี้ ให้ใช้กฎที่เหมาะสมในการสร้างเป้าหมาย 1 รายการเพื่อสร้างโปรเจ็กต์ มาดูเคล็ดลับบางส่วนกัน

    • ใช้กฎที่เหมาะสมดังนี้

      • หากต้องการสร้างโปรเจ็กต์ด้วยโมดูล 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: ใช้เสียงเพื่อแสดงทรัพยากรทั้งหมดในโปรเจ็กต์
      • deps: คุณต้องกำหนดทรัพยากร Dependency ภายนอกที่โปรเจ็กต์ของคุณต้องการ เช่น หากคุณสร้างรายการการขึ้นต่อกันภายนอกโดยใช้เครื่องมือ generate_workspace ทรัพยากร Dependency สำหรับ java_library จะเป็นไลบรารีที่แสดงในมาโคร generated_java_libraries
    • ลองดูตัวอย่างด้านล่างของไฟล์ BUILD ระดับบนสุดนี้จากการย้ายข้อมูลของโปรเจ็กต์ Guava

  3. ตอนนี้คุณมีไฟล์ BUILD ที่รูทของโปรเจ็กต์แล้ว ให้สร้างโปรเจ็กต์เพื่อให้แน่ใจว่าทำงานได้ ในบรรทัดคำสั่ง ให้ใช้ bazel build //:everything จากไดเรกทอรีพื้นที่ทำงานเพื่อสร้างโปรเจ็กต์ด้วย Bazel

    ตอนนี้โปรเจ็กต์ได้สร้างด้วย Bazel เสร็จสมบูรณ์แล้ว คุณจะต้องเพิ่มไฟล์ BUILD อีกเพื่อให้มีการเพิ่มขึ้นของโปรเจ็กต์

ตัวอย่างโปรเจ็กต์ Guava: เริ่มต้นด้วยไฟล์ BUILD ไฟล์เดียว

เมื่อย้ายข้อมูลโปรเจ็กต์ Guava ไปยัง Bazel ในตอนแรกจะมีการใช้ไฟล์ BUILD 1 ไฟล์เพื่อสร้างทั้งโปรเจ็กต์ เนื้อหาของไฟล์ BUILD เริ่มต้นในไดเรกทอรี Workspace มีดังนี้

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 เพียง 1 รายการเท่านั้น ตามที่คุณเห็นหลังจากสร้างเสร็จเป็นครั้งแรก คุณควรพิจารณาแบ่งบิลด์ออกเป็นกลุ่มเล็กๆ ด้วยการเพิ่มไฟล์ BUILD ที่มีเป้าหมายแบบละเอียด

ไฟล์ BUILD หลายไฟล์ที่มีหลายเป้าหมายจะทำให้บิลด์มีความละเอียดมากขึ้น ซึ่งช่วยให้ทำสิ่งต่อไปนี้ได้

  • ได้งานสร้างของโปรเจ็กต์เพิ่มขึ้น
  • เพิ่มการดำเนินการพร้อมกันของบิลด์
  • ความสามารถในการบำรุงรักษาบิลด์สำหรับผู้ใช้ในอนาคตได้ดีขึ้น และ
  • ควบคุมระดับการเข้าถึงเป้าหมายระหว่างแพ็กเกจได้ ซึ่งจะป้องกันปัญหาต่างๆ เช่น ไลบรารีที่มีรายละเอียดการใช้งานรั่วไหลใน API สาธารณะ

เคล็ดลับในการเพิ่มไฟล์ BUILD เพิ่มเติม

  • คุณสามารถเริ่มต้นด้วยการเพิ่มไฟล์ BUILD ลงในแพ็กเกจ Java แต่ละแพ็กเกจ เริ่มต้นด้วยแพ็กเกจ Java ที่มีทรัพยากร Dependency น้อยที่สุดและทำงานได้จนถึงแพ็กเกจที่มีทรัพยากร Dependency มากที่สุด
  • เมื่อคุณเพิ่มไฟล์ BUILD รายการและระบุเป้าหมายแล้ว ให้เพิ่มเป้าหมายใหม่เหล่านี้ในส่วน deps ของเป้าหมายที่เกี่ยวข้อง โปรดทราบว่าฟังก์ชัน glob() ไม่ข้ามขอบเขตของแพ็กเกจ ดังนั้นเมื่อจำนวนแพ็กเกจเพิ่มจำนวนขึ้น ไฟล์ที่ตรงกับ glob() จะลดขนาดลง
  • ทุกครั้งที่คุณเพิ่มไฟล์ BUILD ในไดเรกทอรี main โปรดตรวจสอบว่าได้เพิ่มไฟล์ BUILD ในไดเรกทอรี test ที่ตรงกัน
  • ตรวจสอบการจำกัดระดับการเข้าถึงระหว่างแพ็กเกจอย่างเหมาะสม
  • โปรดตรวจสอบว่าโปรเจ็กต์ยังคงสร้างด้วย Bazel ในขณะที่คุณเพิ่มไฟล์บิลด์แต่ละรายการ เพื่อให้แก้ปัญหาข้อผิดพลาดในการตั้งค่าไฟล์ BUILD ได้ง่ายขึ้น เรียกใช้ bazel build //... เพื่อให้แน่ใจว่าเป้าหมายทั้งหมดยังคงสร้างได้

4. สร้างโดยใช้ Bazel

คุณได้สร้างโดยใช้ Bazel ขณะเพิ่มไฟล์ BUILD ไฟล์เพื่อตรวจสอบการตั้งค่าบิลด์

เมื่อมีไฟล์ BUILD แบบละเอียดที่ต้องการ คุณสามารถใช้ Bazel เพื่อสร้างบิลด์ทั้งหมดได้