โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีหลายเวอร์ชัน ซึ่งแต่ละเวอร์ชันจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่โมดูลนั้นขึ้นอยู่ด้วย ซึ่งคล้ายกับแนวคิดที่คุ้นเคยในระบบการจัดการทรัพยากร Dependency อื่นๆ เช่น อาร์ติแฟกต์ของ Maven, แพ็กเกจของ npm, โมดูลของ Go หรือ เครตของ Cargo
โมดูลต้องมีไฟล์ MODULE.bazel ที่รูท repo ไฟล์นี้คือไฟล์ 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 ของโมดูลรูท จากนั้นจะขอไฟล์
MODULE.bazel ของทรัพยากร Dependency จากรีจิสทรี Bazel ซ้ำๆ จนกว่าจะ
ค้นพบกราฟทรัพยากร Dependency ทั้งหมด
โดยค่าเริ่มต้น Bazel จะเลือกโมดูลแต่ละเวอร์ชัน ที่จะใช้ Bazel จะแสดงโมดูลแต่ละรายการด้วย repo และจะปรึกษาข้อมูลจากรีจิสทรีอีกครั้งเพื่อดูวิธีกำหนด repo แต่ละรายการ
รูปแบบเวอร์ชัน
Bazel มีระบบนิเวศที่หลากหลายและโปรเจ็กต์ต่างๆ ใช้รูปแบบการกำหนดเวอร์ชันที่แตกต่างกัน รูปแบบที่ได้รับความนิยมมากที่สุดคือ SemVer แต่ก็มีโปรเจ็กต์ที่โดดเด่นซึ่งใช้รูปแบบอื่นด้วย เช่น Abseil ซึ่งเวอร์ชันจะอิงตามวันที่ เช่น 20210324.2
ด้วยเหตุนี้ Bazel จึงใช้ข้อกำหนด SemVer เวอร์ชันที่ยืดหยุ่นมากขึ้น โดยมีข้อแตกต่างดังนี้
- SemVer กำหนดว่าส่วน "การเผยแพร่" ของเวอร์ชันต้องประกอบด้วย 3 ส่วน ได้แก่
MAJOR.MINOR.PATCHใน Bazel ข้อกำหนดนี้จะยืดหยุ่นมากขึ้นเพื่อให้มีจำนวนส่วนเท่าใดก็ได้ - ใน SemVer ส่วนต่างๆ ในส่วน "การเผยแพร่" ต้องเป็นตัวเลขเท่านั้น ใน Bazel ข้อกำหนดนี้จะยืดหยุ่นมากขึ้นเพื่อให้ใช้ตัวอักษรได้ด้วย และความหมายของการเปรียบเทียบจะตรงกับ "ตัวระบุ" ในส่วน "เวอร์ชันก่อนเผยแพร่"
- นอกจากนี้ ระบบยังไม่ได้บังคับใช้ความหมายของการเพิ่มเวอร์ชันหลัก เวอร์ชันย่อย และเวอร์ชันแพตช์ อย่างไรก็ตาม โปรดดูรายละเอียดเกี่ยวกับวิธีที่เราระบุความเข้ากันได้แบบย้อนหลังได้ที่ ระดับความเข้ากันได้ สำหรับ
เวอร์ชัน SemVer ที่ถูกต้องจะเป็นเวอร์ชันโมดูล Bazel ที่ถูกต้อง นอกจากนี้ เวอร์ชัน SemVer 2 เวอร์ชัน
a และ b จะเปรียบเทียบ a < b ก็ต่อเมื่อเป็นจริงเมื่อ
เปรียบเทียบเป็นเวอร์ชันโมดูล Bazel
สุดท้ายนี้ หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดเวอร์ชันโมดูล โปรดดูMODULE.bazel
คำถามที่พบบ่อย
การเลือกเวอร์ชัน
พิจารณาปัญหาทรัพยากร Dependency แบบไดมอนด์ ซึ่งเป็นปัญหาหลักในการจัดการทรัพยากร Dependency ที่กำหนดเวอร์ชัน สมมติว่าคุณมีกราฟทรัพยากร Dependency ดังนี้
A 1.0
/ \
B 1.0 C 1.1
| |
D 1.0 D 1.1
ควรใช้ D เวอร์ชันใด Bazel ใช้
การเลือกเวอร์ชันต่ำสุด
(MVS) ซึ่งเป็นอัลกอริทึมที่แนะนำในระบบโมดูล Go เพื่อแก้ปัญหานี้ MVS สันนิษฐานว่าโมดูลเวอร์ชันใหม่ทั้งหมดเข้ากันได้แบบย้อนหลัง จึงเลือกเวอร์ชันสูงสุดที่ระบุโดยทรัพยากร Dependency (D 1.1 ในตัวอย่างของเรา) โดยเรียกว่า "ต่ำสุด" เนื่องจาก D 1.1 เป็นเวอร์ชันแรกสุดที่ตรงตามข้อกำหนดของเรา แม้ว่าจะมี D 1.2 หรือเวอร์ชันใหม่กว่า เราก็จะไม่เลือก การใช้ MVS จะสร้างกระบวนการเลือกเวอร์ชันที่มี ความแม่นยำสูงและ ทำซ้ำได้
เวอร์ชันที่ถูกยกเลิก
รีจิสทรีสามารถประกาศเวอร์ชันบางเวอร์ชันเป็น เวอร์ชันที่ถูกยกเลิกหากควรหลีกเลี่ยง (เช่น เวอร์ชันที่มีช่องโหว่ด้านความปลอดภัย) Bazel จะแสดงข้อผิดพลาดเมื่อเลือกโมดูลเวอร์ชันที่ถูกยกเลิก หากต้องการแก้ไขข้อผิดพลาดนี้ ให้อัปเกรดเป็นเวอร์ชันใหม่กว่า
ที่ไม่ได้ถูกยกเลิก หรือใช้
--allow_yanked_versions
แฟล็กเพื่ออนุญาตเวอร์ชันที่ถูกยกเลิกอย่างชัดเจน
ระดับความเข้ากันได้
ใน Go การสันนิษฐานของ MVS เกี่ยวกับความเข้ากันได้แบบย้อนหลังได้ผลเนื่องจาก MVS ถือว่าโมดูลเวอร์ชันที่เข้ากันไม่ได้แบบย้อนหลังเป็นโมดูลแยกต่างหาก ในแง่ของ SemVer หมายความว่า A 1.x และ A 2.x ถือเป็นโมดูลที่แตกต่างกัน และสามารถอยู่ร่วมกันในกราฟทรัพยากร Dependency ที่แก้ปัญหาแล้ว ซึ่งเป็นไปได้เนื่องจากการเข้ารหัสเวอร์ชันหลักในเส้นทางแพ็กเกจใน Go จึงไม่มีความขัดแย้งในเวลาคอมไพล์หรือเวลาลิงก์ อย่างไรก็ตาม Bazel ไม่สามารถรับประกันได้เช่นนั้น
เนื่องจากใช้ SemVer เวอร์ชันที่ยืดหยุ่น
ดังนั้น Bazel จึงต้องมีสิ่งที่เทียบเท่ากับหมายเลขเวอร์ชันหลักของ SemVer เพื่อตรวจหาเวอร์ชันที่เข้ากันไม่ได้แบบย้อนหลัง ("เวอร์ชันที่ทำให้เกิดการเปลี่ยนแปลงที่สำคัญ") หมายเลขนี้เรียกว่า
ระดับความเข้ากันได้และระบุโดยโมดูลแต่ละเวอร์ชันในคำสั่ง
module() ข้อมูลนี้ช่วยให้ Bazel แสดงข้อผิดพลาดได้หากตรวจพบว่ามี โมดูลเดียวกันที่มี ระดับความเข้ากันได้ต่างกันอยู่ในกราฟทรัพยากร Dependency ที่แก้ปัญหาแล้ว
สุดท้ายนี้ การเพิ่มระดับความเข้ากันได้อาจส่งผลกระทบต่อผู้ใช้
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเวลาและวิธีเพิ่มระดับความเข้ากันได้ โปรดดูMODULE.bazel
คำถามที่พบบ่อย
ลบล้าง
ระบุการลบล้างในไฟล์ MODULE.bazel เพื่อเปลี่ยนลักษณะการทำงานของการแก้ปัญหาโมดูล Bazel การลบล้างของโมดูลรูทเท่านั้นที่จะมีผล หากใช้โมดูลเป็นทรัพยากร Dependency ระบบจะละเว้นการลบล้างของโมดูลนั้น
การลบล้างแต่ละรายการจะระบุไว้สำหรับชื่อโมดูลหนึ่งๆ ซึ่งจะส่งผลต่อโมดูลทุกเวอร์ชันในกราฟทรัพยากร Dependency แม้ว่าการลบล้างของโมดูลรูทเท่านั้นที่จะมีผล แต่การลบล้างนั้นอาจใช้กับทรัพยากร Dependency แบบทรานซิทีฟที่โมดูลรูทไม่ได้ขึ้นอยู่ด้วยโดยตรง
การลบล้างเวอร์ชันเดียว
single_version_override
มีวัตถุประสงค์หลายประการ ดังนี้
- แอตทริบิวต์
versionช่วยให้คุณตรึงทรัพยากร Dependency ไว้กับเวอร์ชันที่เฉพาะเจาะจงได้ ไม่ว่าเวอร์ชันใดของทรัพยากร Dependency จะมีการขอในกราฟทรัพยากร Dependency - แอตทริบิวต์
registryช่วยให้คุณบังคับให้ทรัพยากร Dependency นี้มาจากรีจิสทรีที่ เฉพาะเจาะจงได้ แทนที่จะทำตามกระบวนการ เลือกรีจิสทรี ตามปกติ - แอตทริบิวต์
patch*ช่วยให้คุณระบุชุดแพตช์ที่จะใช้กับโมดูลที่ดาวน์โหลดได้
แอตทริบิวต์เหล่านี้เป็นแอตทริบิวต์ที่ไม่บังคับทั้งหมด และสามารถใช้ร่วมกันได้
การลบล้างหลายเวอร์ชัน
คุณระบุ multiple_version_override
เพื่ออนุญาตให้โมดูลเดียวกันหลายเวอร์ชันอยู่ร่วมกันใน
กราฟทรัพยากร Dependency ที่แก้ปัญหาแล้วได้
คุณสามารถระบุรายการเวอร์ชันที่อนุญาตอย่างชัดเจนสำหรับโมดูล ซึ่งเวอร์ชันทั้งหมดต้องอยู่ในกราฟทรัพยากร 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 ซึ่งคล้ายกับการลบล้างเวอร์ชันเดียว
การลบล้างที่ไม่ใช่รีจิสทรี
การลบล้างที่ไม่ใช่รีจิสทรีจะนำโมดูลออกจากกระบวนการแก้ปัญหาเวอร์ชันโดยสมบูรณ์ Bazel จะไม่ขอไฟล์ MODULE.bazel เหล่านี้จากรีจิสทรี แต่จะขอจาก repo เอง
Bazel รองรับการลบล้างที่ไม่ใช่รีจิสทรีต่อไปนี้
โปรดทราบว่าการตั้งค่าค่าเวอร์ชันใน MODULE.bazel ของไฟล์เก็บถาวรต้นทางอาจมีข้อเสียเมื่อมีการลบล้างโมดูลด้วยการลบล้างที่ไม่ใช่รีจิสทรี หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ โปรดดูคำถามที่พบบ่อยMODULE.bazel
กำหนด repo ที่ไม่ได้แสดงโมดูล Bazel
bazel_dep ช่วยให้คุณกำหนด repo ที่แสดงโมดูล Bazel อื่นๆ ได้
บางครั้งคุณอาจต้องกำหนด repo ที่ ไม่ได้แสดงโมดูล Bazel เช่น repo ที่มีไฟล์ JSON ธรรมดาที่จะอ่านเป็นข้อมูล
ในกรณีนี้ คุณสามารถใช้คำสั่ง use_repo_rule
directive เพื่อกำหนด repo โดยตรง
โดยการเรียกใช้กฎของ repo โมดูลที่กำหนด repo นี้ไว้เท่านั้นที่จะมองเห็น repo นี้
เบื้องหลังการทำงาน ระบบจะใช้กลไกเดียวกับส่วนขยาย โมดูล ซึ่งช่วยให้คุณกำหนด repo ได้อย่างยืดหยุ่นมากขึ้น
ชื่อที่เก็บและทรัพยากร Dependency ที่เข้มงวด
ชื่อที่ปรากฏของ repo ที่รองรับ
โมดูลสำหรับทรัพยากร Dependency โดยตรงจะเป็นชื่อโมดูลโดยค่าเริ่มต้น เว้นแต่
repo_name แอตทริบิวต์ของคำสั่งbazel_dep
จะระบุไว้เป็นอย่างอื่น โปรดทราบว่าหมายความว่าโมดูลจะค้นหาได้เฉพาะทรัพยากร Dependency โดยตรงเท่านั้น ซึ่งจะช่วยป้องกันการหยุดทำงานโดยไม่ตั้งใจเนื่องจากการเปลี่ยนแปลงในทรัพยากร Dependency แบบทรานซิทีฟ
ชื่อ Canonical ของ repo ที่รองรับ
โมดูลคือ module_name+version (เช่น bazel_skylib+1.0.3) หรือ module_name+ (เช่น bazel_features+) ทั้งนี้ขึ้นอยู่กับว่ามี
โมดูลหลายเวอร์ชันในกราฟทรัพยากร Dependency ทั้งหมดหรือไม่ (ดู
multiple_version_override)
โปรดทราบว่า รูปแบบชื่อ Canonical ไม่ใช่ API ที่คุณควรใช้และ
อาจมีการเปลี่ยนแปลงได้ทุกเมื่อ ให้ใช้วิธีที่รองรับเพื่อรับชื่อ Canonical จาก Bazel โดยตรงแทนการฮาร์ดโค้ดชื่อ Canonical
- ในไฟล์ BUILD และ
.bzlให้ใช้Label.repo_nameในอินสแตนซ์Labelที่สร้างจากสตริงป้ายกำกับที่กำหนดโดยชื่อที่ปรากฏของ repo เช่น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เพื่อรับการแมปจาก ชื่อที่ปรากฏเป็นชื่อ Canonical สำหรับชุดที่เก็บข้อมูลที่กำหนด
ส่วนขยายโมดูลยังสามารถนำ repo เพิ่มเติม มาไว้ในขอบเขตที่มองเห็นได้ของโมดูลได้ด้วย