โมดูล Bazel

รายงานปัญหา ดูแหล่งที่มา รุ่น Nightly · 7.4 7.3 · 7.2 · 7.1 · 7.0 · 6.5

โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน โดยแต่ละเวอร์ชัน ซึ่งจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่จะขึ้นอยู่กับโมดูลนั้นๆ ซึ่งคล้ายกับแนวคิดที่คุ้นเคยในระบบการจัดการทรัพยากรอื่นๆ เช่น อาร์ติแฟกต์ Maven, แพ็กเกจ npm, โมดูล Go หรือ Crate ของ Cargo

โมดูลต้องมีไฟล์ MODULE.bazel ที่รูทที่เก็บ ไฟล์นี้เป็นไฟล์ Manifest ของโมดูล ซึ่งจะประกาศชื่อ เวอร์ชัน รายการของข้อกําหนดโดยตรง และข้อมูลอื่นๆ ตัวอย่างเบื้องต้นมีดังนี้

module(name = "my-module", version = "1.0")

bazel_dep(name = "rules_cc", version = "0.0.1")
bazel_dep(name = "protobuf", version = "3.19.0")

ดูรายการทั้งหมดของคําสั่งที่มีอยู่ในไฟล์MODULE.bazel

ในการแก้ไขข้อขัดข้องของโมดูล Bazel จะเริ่มด้วยการอ่านไฟล์ MODULE.bazel ของโมดูลรูท จากนั้นจะขอไฟล์ MODULE.bazel ของข้อกำหนดต่างๆ จาก รีจิสทรี Bazel ซ้ำๆ จนกว่าจะพบกราฟข้อกำหนดทั้งหมด

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

รูปแบบเวอร์ชัน

Bazel มีระบบนิเวศที่หลากหลาย และโปรเจ็กต์ต่างๆ ก็ใช้รูปแบบการกำหนดเวอร์ชันที่หลากหลาย รูปแบบที่ได้รับความนิยมมากที่สุดคือ SemVer แต่ก็มีโปรเจ็กต์ที่โดดเด่นซึ่งใช้รูปแบบอื่นด้วย เช่น Abseil ซึ่งเวอร์ชันจะอิงตามวันที่ เช่น 20210324.2)

ด้วยเหตุนี้ Bzlmod จึงใช้ข้อกำหนด SemVer เวอร์ชันที่ผ่อนปรนมากขึ้น โดยความแตกต่างมีดังนี้

  • SemVer กำหนดให้ส่วน "release" ของเวอร์ชันประกอบด้วยกลุ่มย่อย 3 กลุ่ม ดังนี้ MAJOR.MINOR.PATCH ใน Bazel ข้อกำหนดนี้ได้ผ่อนปรนแล้ว อนุญาตให้มีกลุ่มจำนวนเท่าใดก็ได้
  • ใน SemVer แต่ละส่วนใน "รุ่น" ส่วนต้องเป็นตัวเลขเท่านั้น ใน Bazel กฎนี้มีความยืดหยุ่นมากขึ้นเพื่ออนุญาตให้ใช้ตัวอักษรได้ด้วย และความหมายของการเปรียบเทียบจะตรงกับ "ตัวระบุ" ในส่วน "รุ่นก่อนเผยแพร่"
  • นอกจากนี้ ระบบจะไม่บังคับใช้ความหมายของการเพิ่มเวอร์ชันหลัก เวอร์ชันย่อย และเวอร์ชันแพตช์ โปรดดูระดับความเข้ากันได้สำหรับ รายละเอียดว่าเราแสดงถึงความเข้ากันได้แบบย้อนหลังได้อย่างไร

เวอร์ชัน SemVer ที่ถูกต้องคือเวอร์ชันโมดูล Bazel ที่ถูกต้อง นอกจากนี้ SemVer เวอร์ชัน a และ b จะเปรียบเทียบ a < b ก็ต่อเมื่อมีการคงไว้ชั่วคราวเดียวกันเมื่อ และถูกเปรียบเทียบด้วยเวอร์ชันโมดูล Bazel

การเลือกเวอร์ชัน

ลองพิจารณาปัญหาเกี่ยวกับการขึ้นต่อกันแบบไดมอนด์ ซึ่งเป็นองค์ประกอบหลักในทรัพยากร Dependency ที่มีเวอร์ชัน พื้นที่จัดการ สมมติว่าคุณมีกราฟทรัพยากร Dependency ไว้

       A 1.0
      /     \
   B 1.0    C 1.1
     |        |
   D 1.0    D 1.1

ฉันควรใช้ D เวอร์ชันใด ในการแก้ปัญหานี้ Bzlmod ใช้ การเลือกเวอร์ชันขั้นต่ำ (MVS) ที่เปิดตัวในระบบโมดูล Go MVS ถือว่าใหม่ทั้งหมด โมดูลที่เข้ากันได้แบบย้อนหลัง ดังนั้นจึงควรเลือกเวอร์ชันสูงสุด ที่ระบุโดยการอ้างอิงใดก็ได้ (D 1.1 ในตัวอย่าง) เรียกว่า "ขั้นต่ำสุด" เนื่องจาก D 1.1 เป็นเวอร์ชันแรกสุดที่สามารถตรงตามข้อกำหนดของเรา แม้ว่าจะมี D 1.2 หรือรุ่นที่ใหม่กว่า เราจะไม่เลือกให้ การใช้ MVS จะสร้างกระบวนการเลือกเวอร์ชันที่มีความแม่นยำสูงและทำซ้ำได้

เวอร์ชันแย้ง

รีจิสทรีสามารถประกาศบางเวอร์ชันเป็น yanked ได้หากควรหลีกเลี่ยง (เช่น สำหรับช่องโหว่ด้านความปลอดภัย) Bazel จะแสดงข้อผิดพลาดเมื่อเลือกเวอร์ชันที่ยกเลิกของโมดูล ในการแก้ไขข้อผิดพลาดนี้ ให้อัปเกรดเป็นเวอร์ชันใหม่ ไม่ใช่เวอร์ชันเพิ่มเติม หรือใช้ --allow_yanked_versions เพื่ออนุญาตเวอร์ชันที่แยกอย่างชัดเจน

ระดับความเข้ากันได้

ใน Go สมมติฐานของ MVS เกี่ยวกับการทำงานร่วมกันแบบย้อนหลังจะใช้งานได้เนื่องจากระบบจะถือว่าโมดูลเวอร์ชันที่เข้ากันไม่ได้แบบย้อนหลังเป็นโมดูลแยกต่างหาก ในแง่ของ SemVer ซึ่งหมายความว่า A 1.x และ A 2.x ถือเป็นโมดูลที่แตกต่างกัน และ อยู่ร่วมกันในกราฟทรัพยากร Dependency ที่ได้รับการแก้ไข ซึ่งทำได้โดยการเข้ารหัสเวอร์ชันหลักในเส้นทางแพ็กเกจใน Go เพื่อให้ไม่มีข้อขัดแย้งเกิดขึ้นในเวลาคอมไพล์หรือเวลาลิงก์

อย่างไรก็ตาม Bazel ไม่สามารถรับประกันดังกล่าว จึงต้องใช้ "เวอร์ชันหลัก" เพื่อตรวจหาเวอร์ชันที่ใช้ร่วมกันไม่ได้ย้อนหลัง หมายเลขนี้โทรหา ระดับความเข้ากันได้ และระบุโดยเวอร์ชันโมดูลแต่ละเวอร์ชันใน คำสั่ง module() ข้อมูลนี้ทำให้ Bazel แสดงข้อผิดพลาดได้เมื่อ ตรวจพบว่าโมดูลเดียวกันในเวอร์ชันเดียวกันที่มีระดับความเข้ากันได้แตกต่างกัน อยู่ในกราฟทรัพยากร Dependency ที่ได้รับการแก้ไข

ลบล้าง

ระบุการลบล้างในไฟล์ MODULE.bazel เพื่อเปลี่ยนลักษณะการทำงานของ Bazel ความละเอียดของโมดูล เฉพาะการลบล้างของโมดูลรูทเท่านั้นที่มีผล หากโมดูลคือ ที่ใช้เป็นทรัพยากร Dependency จะถูกละเว้น

การลบล้างแต่ละรายการถูกระบุสำหรับชื่อโมดูลหนึ่งๆ ซึ่งส่งผลต่อ เวอร์ชันในกราฟทรัพยากร Dependency แม้ว่าจะมีเฉพาะการลบล้างของโมดูลรูทเท่านั้นที่มีผล แต่การลบล้างดังกล่าวอาจใช้กับข้อกําหนดเบื้องต้นแบบเปลี่ยนผ่านที่โมดูลรูทไม่ได้ใช้โดยตรง

การลบล้างเวอร์ชันเดียว

single_version_override ใช้เพื่อวัตถุประสงค์หลายอย่าง ดังนี้

  • คุณสามารถใช้แอตทริบิวต์ version เพื่อปักหมุดทรัพยากร Dependency ได้ ไม่ว่าจะมีการขอทรัพยากร Dependency เวอร์ชันใดก็ตามใน กราฟการขึ้นต่อกัน
  • เมื่อใช้แอตทริบิวต์ registry คุณสามารถบังคับให้ทรัพยากรนี้มาจากรีจิสทรีที่เฉพาะเจาะจงแทนที่จะทำตามกระบวนการการเลือกรีจิสทรีตามปกติ
  • คุณระบุชุดแพตช์ที่จะใช้ได้ด้วยแอตทริบิวต์ patch* โมดูลที่ดาวน์โหลดแล้ว

แอตทริบิวต์เหล่านี้ไม่บังคับและสามารถผสมผสานกัน

การลบล้างแบบหลายเวอร์ชัน

multiple_version_override สามารถระบุเพื่อให้โมดูลเดียวกันหลายเวอร์ชันอยู่ร่วมกันใน กราฟทรัพยากร Dependency ที่ได้รับการแก้ไขแล้ว

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

ตัวอย่างเช่น ถ้ามีเวอร์ชัน 1.1, 1.3, 1.5, 1.7 และ 2.0 อยู่ใน กราฟทรัพยากร Dependency ก่อนแก้ปัญหาและเวอร์ชันหลักคือความเข้ากันได้ ระดับ:

  • การลบล้างหลายเวอร์ชันที่อนุญาต 1.3, 1.7 และ 2.0 จะส่งผลให้1.1ได้รับการอัปเกรดเป็น 1.3, 1.5 ได้รับการอัปเกรดเป็น 1.7 และเวอร์ชันอื่นๆ ยังคงเหมือนเดิม
  • การลบล้างแบบหลายเวอร์ชันที่อนุญาต 1.5 และ 2.0 ทำให้เกิดข้อผิดพลาด เช่น 1.7 ไม่มีเวอร์ชันที่สูงกว่าซึ่งมีระดับความเข้ากันได้ที่ระดับเดียวกันให้อัปเกรด
  • การลบล้างหลายเวอร์ชันที่อนุญาต 1.9 และ 2.0 จะทำให้เกิดข้อผิดพลาดเนื่องจาก 1.9 ไม่อยู่ในกราฟความเกี่ยวข้องก่อนการแก้ไข

นอกจากนี้ ผู้ใช้ยังลบล้างรีจิสทรีโดยใช้ registry ได้ด้วย ซึ่งคล้ายกับการลบล้างเวอร์ชันเดียว

การลบล้างที่ไม่ใช่รีจิสทรี

การลบล้างที่ไม่ใช่รีจิสทรีจะนำโมดูลออกจากการแปลงเวอร์ชันโดยสมบูรณ์ บาเซล ไม่ขอไฟล์ MODULE.bazel รายการนี้จากรีจิสทรี แต่ขอจาก ที่เก็บได้นั้นเอง

Bazel รองรับการลบล้างที่ไม่ใช่รีจิสทรีต่อไปนี้

กำหนดที่เก็บที่ไม่ได้แสดงถึงโมดูล Bazel

bazel_dep ช่วยให้คุณกำหนดที่เก็บซึ่งแสดงโมดูล Bazel อื่นๆ ได้ บางครั้งจำเป็นต้องกำหนดที่เก็บซึ่งไม่ได้แสดงโมดูล Bazel เช่น ที่เก็บที่มีไฟล์ JSON ธรรมดาที่จะอ่านเป็นข้อมูล

ในกรณีนี้ คุณสามารถใช้use_repo_rule คำสั่งเพื่อกำหนดที่เก็บโดยตรง โดยการเรียกใช้กฎที่เก็บ ที่เก็บนี้จะปรากฏต่อโมดูล กำหนดไว้ใน

เบื้องหลัง ระบบจะใช้กลไกเดียวกับส่วนขยายของข้อบังคับ ซึ่งช่วยให้คุณกำหนดที่เก็บได้อย่างยืดหยุ่นมากขึ้น

ชื่อที่เก็บและหน่วยงานที่เข้มงวด

ชื่อที่ปรากฏของรีโปที่สำรองข้อมูลโมดูลให้กับโมดูลที่ขึ้นต่อกันโดยตรงจะเป็นชื่อโมดูลโดยค่าเริ่มต้น เว้นแต่แอตทริบิวต์ repo_name ของคำสั่ง bazel_dep จะระบุไว้เป็นอย่างอื่น ซึ่งหมายความว่าโมดูลจะดูได้เฉพาะ ทรัพยากร Dependency ซึ่งจะช่วยป้องกันความเสียหายโดยไม่ตั้งใจที่เกิดจากการเปลี่ยนแปลงในข้อกำหนดเบื้องต้นแบบทรานซิทีฟ

ชื่อ Canonical ของที่เก็บที่รองรับ โมดูลเป็น module_name+version (เช่น bazel_skylib+1.0.3) หรือ module_name+ (เช่น bazel_features+) ขึ้นอยู่กับว่ามีโมดูลใด โมดูลต่างๆ ในหลายเวอร์ชันในกราฟทรัพยากร Dependency ทั้งหมด (โปรดดู multiple_version_override) โปรดทราบว่ารูปแบบชื่อ Canonical ไม่ใช่ API ที่คุณควรใช้ และ อาจเปลี่ยนแปลงได้ทุกเมื่อ แทนที่จะฮาร์ดโค้ดชื่อ Canonical ใช้วิธีการที่รองรับเพื่อรับข้อความจาก Bazel โดยตรง ดังนี้ * ในไฟล์ BUILD และ .bzl ให้ใช้ Label.repo_name บนอินสแตนซ์ Label สร้างขึ้นจากสตริงป้ายกำกับที่ระบุโดยชื่อที่ปรากฏของที่เก็บ เช่น Label("@bazel_skylib").repo_name * เมื่อค้นหาไฟล์รันไทม์ ให้ใช้ $(rlocationpath ...) หรือไลบรารีไฟล์รันไทม์รายการใดรายการหนึ่งใน @bazel_tools//tools/{bash,cpp,java}/runfiles หรือสำหรับชุดกฎ rules_foo ให้ใช้ @rules_foo//foo/runfiles * เมื่อโต้ตอบกับ Bazel จากเครื่องมือภายนอก เช่น IDE หรือภาษา ให้ใช้คำสั่ง bazel mod dump_repo_mapping เพื่อรับการแมป ชื่อที่ชัดเจนของชื่อตามรูปแบบบัญญัติสำหรับชุดที่เก็บที่ระบุ

ส่วนขยายของโมดูลยังนํารีพอสิทเพิ่มเติมมาไว้ในขอบเขตที่มองเห็นได้ของโมดูลได้ด้วย