โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน โดยแต่ละเวอร์ชัน ซึ่งจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่เกี่ยวข้อง นี่คือ คล้ายกับแนวคิดที่คุ้นเคยในระบบการจัดการทรัพยากร Dependency อื่นๆ เช่น อาร์ติแฟกต์ Maven, แพ็กเกจ npm, โมดูล Go หรือลัง Cargo
โมดูลต้องมีไฟล์ MODULE.bazel
ที่รูทที่เก็บ ไฟล์นี้เป็น
ไฟล์ Manifest ของโมดูล โดยประกาศชื่อ เวอร์ชัน รายการทรัพยากร Dependency โดยตรง และ
ข้อมูลอื่นๆ ตัวอย่างพื้นฐานมีดังนี้
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
แล้วขอทรัพยากร Dependency ต่างๆ ซ้ำหลายครั้ง
MODULE.bazel
ไฟล์จากรีจิสทรีของ Bazel จนกว่าจะมีข้อมูล
จะค้นพบกราฟทรัพยากร Dependency ทั้งหมด
โดยค่าเริ่มต้น Bazel จะเลือกเวอร์ชัน 1 เวอร์ชันของแต่ละโมดูล ในการใช้กัน Bazel แสดงแต่ละโมดูลด้วยที่เก็บ และปรึกษาสำนักทะเบียน อีกครั้งเพื่อเรียนรู้วิธีกำหนดที่เก็บแต่ละรายการ
รูปแบบเวอร์ชัน
Bazel มีระบบนิเวศที่หลากหลาย และโปรเจ็กต์ต่างๆ ก็ใช้รูปแบบการกำหนดเวอร์ชันที่หลากหลาย
ยอดนิยมที่สุดจนถึงตอนนี้คือ SemVer แต่ก็มี
รวมไปถึงโครงการที่โดดเด่นโดยใช้แผนการต่างๆ เช่น
Abseil ที่
เวอร์ชันจะยึดตามวันที่ เช่น 20210324.2
)
ด้วยเหตุนี้ Bzlmod จึงใช้ข้อกำหนดของ SemVer เวอร์ชันที่ผ่อนคลายมากกว่า ความแตกต่างมีดังนี้
- SemVer กำหนดว่าการ "เผยแพร่" ส่วนหนึ่งของเวอร์ชันต้องประกอบด้วย 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 ที่ได้รับการแก้ไขแล้ว
คุณสามารถระบุรายการเวอร์ชันที่อนุญาตของโมดูลอย่างชัดแจ้ง ซึ่งต้อง ทั้งหมดจะแสดงในกราฟทรัพยากร 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
ไม่ปรากฏในกราฟทรัพยากร Dependency ก่อนแก้ปัญหา
นอกจากนี้ ผู้ใช้ยังลบล้างรีจิสทรีโดยใช้ registry
ได้ด้วย
ซึ่งคล้ายกับการลบล้างเวอร์ชันเดียว
การลบล้างที่ไม่ใช่รีจิสทรี
การลบล้างที่ไม่ใช่รีจิสทรีจะนำโมดูลออกจากการแปลงเวอร์ชันโดยสมบูรณ์ บาเซล
ไม่ขอไฟล์ MODULE.bazel
รายการนี้จากรีจิสทรี แต่ขอจาก
ที่เก็บได้นั้นเอง
Bazel รองรับการลบล้างที่ไม่ใช่รีจิสทรีต่อไปนี้
กำหนดที่เก็บที่ไม่ได้แสดงถึงโมดูล Bazel
เมื่อใช้ bazel_dep
คุณจะกำหนดที่เก็บที่แสดงถึงโมดูล Bazel อื่นๆ ได้
บางครั้งอาจต้องกำหนดที่เก็บที่ไม่ได้เป็นตัวแทนของ Bazel
module; เช่น ไฟล์ที่มีไฟล์ JSON ธรรมดาที่จะอ่านเป็นข้อมูล
ในกรณีนี้ คุณสามารถใช้use_repo_rule
คำสั่งเพื่อกำหนดที่เก็บโดยตรง
โดยการเรียกใช้กฎที่เก็บ ที่เก็บนี้จะปรากฏต่อโมดูล
กำหนดไว้ใน
กลไกภายในระบบนี้ติดตั้งโดยใช้กลไกเดียวกับโมดูล ส่วนขยาย ซึ่งจะช่วยให้คุณกำหนดที่เก็บโดยมี และความยืดหยุ่น
ชื่อที่เก็บและหน่วยงานที่เข้มงวด
ชื่อที่ปรากฏของที่เก็บที่สนับสนุน
ไปยังปลายทางโดยตรงของโมดูลที่มีค่าเริ่มต้นเป็นชื่อโมดูล เว้นแต่ว่า
แอตทริบิวต์ repo_name
ของ bazel_dep
หรือไม่เช่นนั้น ซึ่งหมายความว่าโมดูลจะดูได้เฉพาะ
ทรัพยากร Dependency วิธีนี้จะช่วยป้องกันการหยุดทำงานโดยไม่ตั้งใจจากการเปลี่ยนแปลงใน
ทรัพยากร 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 ...)
หรือไลบรารี Runfile อันใดอันหนึ่งใน
@bazel_tools//tools/{bash,cpp,java}/runfiles
หรือสำหรับชุดกฎ rules_foo
ใน @rules_foo//foo/runfiles
* เมื่อโต้ตอบกับ Bazel จากเครื่องมือภายนอก เช่น IDE หรือภาษา
ให้ใช้คำสั่ง bazel mod dump_repo_mapping
เพื่อรับการแมป
ชื่อที่ชัดเจนของชื่อตามรูปแบบบัญญัติสำหรับชุดที่เก็บที่ระบุ
ส่วนขยายโมดูลยังแนะนำที่เก็บเพิ่มเติมได้ด้วย ให้อยู่ภายในขอบเขตที่มองเห็นได้ของโมดูล