โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน โดยแต่ละเวอร์ชัน ซึ่งจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่เกี่ยวข้อง นี่คือ คล้ายกับแนวคิดที่คุ้นเคยในระบบการจัดการทรัพยากร Dependency อื่นๆ เช่น อาร์ติแฟกต์ Maven, แพ็กเกจ npm, โมดูล Go หรือลัง Cargo
โมดูลต้องมีไฟล์ MODULE.bazel
ที่รูทที่เก็บ (ถัดจาก
WORKSPACE
) ไฟล์นี้เป็นไฟล์ 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
เพื่อรับการแมป
ชื่อที่ชัดเจนของชื่อตามรูปแบบบัญญัติสำหรับชุดที่เก็บที่ระบุ
ส่วนขยายโมดูลยังแนะนำที่เก็บเพิ่มเติมได้ด้วย ให้อยู่ภายในขอบเขตที่มองเห็นได้ของโมดูล