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

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

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

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

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

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

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

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

ขั้นตอนด้านล่างอธิบายวิธีย้ายข้อมูลโปรเจ็กต์ไปยัง Bazel

  1. สร้างไฟล์ WORKSPACE
  2. สร้างไฟล์ BUILD 1 ไฟล์
  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 1 ไฟล์

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

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

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

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

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

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

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

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

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

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

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

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