Bazel รองรับ การขึ้นต่อกันภายนอก ไฟล์ต้นฉบับ (ทั้งข้อความและไบนารี) ที่ใช้ ในบิลด์ซึ่งไม่ได้มาจากพื้นที่ทำงาน เช่น อาจเป็นชุดกฎที่โฮสต์ในที่เก็บ GitHub, อาร์ติแฟกต์ Maven หรือไดเรกทอรีในเครื่องของคุณนอกพื้นที่ทำงานปัจจุบัน
เอกสารนี้จะให้ภาพรวมของระบบก่อนที่จะดูแนวคิดบางอย่างโดยละเอียด
ภาพรวมของระบบ
ระบบทรัพยากร Dependency ภายนอกของ Bazel ทำงานโดยอิงตาม โมดูล Bazel ซึ่งแต่ละโมดูลเป็นโปรเจ็กต์ Bazel ที่มีเวอร์ชัน และ ที่เก็บ (หรือ repo) ซึ่งเป็นแผนผังไดเรกทอรีที่มี ไฟล์ต้นฉบับ
Bazel จะเริ่มต้นจากโมดูลรูท ซึ่งก็คือโปรเจ็กต์ที่คุณกำลังทำงานอยู่
เช่นเดียวกับโมดูลอื่นๆ โมดูลรูทต้องมีไฟล์ MODULE.bazel ที่รูทไดเรกทอรี ซึ่งประกาศข้อมูลเมตาพื้นฐานและการขึ้นต่อกันโดยตรง ตัวอย่างพื้นฐานมีดังนี้
module(name = "my-module", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")
จากนั้น Bazel จะค้นหาโมดูลทรัพยากร Dependency แบบทรานซิทีฟทั้งหมดใน
รีจิสทรี Bazel ซึ่งโดยค่าเริ่มต้นคือ รีจิสทรีกลาง
ของ Bazel รีจิสทรีจะให้ไฟล์ MODULE.bazel ของทรัพยากร Dependency ซึ่งช่วยให้ Bazel ค้นพบกราฟทรัพยากร Dependency แบบทรานซิทีฟทั้งหมดก่อนที่จะทำการแก้ปัญหาเวอร์ชัน
หลังจากการแก้ปัญหาเวอร์ชัน ซึ่งจะมีการเลือกเวอร์ชันเดียวสำหรับแต่ละโมดูล Bazel จะปรึกษาข้อมูลจากรีจิสทรีอีกครั้งเพื่อดูวิธีกำหนด repo สำหรับแต่ละโมดูล นั่นคือ วิธีดึงข้อมูลต้นฉบับสำหรับโมดูลทรัพยากร Dependency แต่ละโมดูล ส่วนใหญ่แล้วจะเป็นเพียงไฟล์เก็บถาวรที่ดาวน์โหลดจากอินเทอร์เน็ตและแตกไฟล์
โมดูลยังระบุข้อมูลที่กำหนดเองที่เรียกว่า แท็ก ได้ด้วย ซึ่ง ส่วนขยายโมดูลจะใช้แท็กเหล่านี้หลังจากการแก้ปัญหาโมดูล เพื่อกำหนด repo เพิ่มเติม ส่วนขยายเหล่านี้สามารถดำเนินการต่างๆ เช่น I/O ของไฟล์และการส่งคำขอเครือข่าย นอกจากนี้ ส่วนขยายยังช่วยให้ Bazel โต้ตอบกับระบบการจัดการแพ็กเกจอื่นๆ ได้ในขณะที่ยังคงพิจารณากราฟทรัพยากร Dependency ที่สร้างจากโมดูล Bazel
repo 3 ประเภท ได้แก่ repo หลัก (ซึ่งเป็นแผนผังต้นฉบับที่คุณกำลังทำงานอยู่) repo ที่แสดงโมดูลทรัพยากร Dependency แบบทรานซิทีฟ และ repo ที่สร้างโดยส่วนขยายโมดูล จะรวมกันเป็น พื้นที่ทำงาน
ระบบจะดึงข้อมูล repo ภายนอก (repo ที่ไม่ใช่ repo หลัก) ตามความต้องการ เช่น เมื่อมีการอ้างอิง repo เหล่านี้ด้วยป้ายกำกับ (เช่น @repo//pkg:target) ในไฟล์ BUILD
สิทธิประโยชน์
ระบบทรัพยากร Dependency ภายนอกของ Bazel มีข้อดีมากมาย
การแก้ปัญหาการขึ้นต่อกันโดยอัตโนมัติ
- การแก้ปัญหาเวอร์ชันเชิงกำหนด: Bazel ใช้MVS อัลกอริทึมการแก้ปัญหาเวอร์ชันเชิงกำหนด ซึ่งช่วยลดความขัดแย้งและแก้ปัญหาทรัพยากร Dependency แบบไดมอนด์
- การจัดการทรัพยากร Dependency ที่ง่ายขึ้น:
MODULE.bazelจะประกาศเฉพาะทรัพยากร Dependency โดยตรง ขณะที่ระบบจะแก้ปัญหาทรัพยากร Dependency แบบทรานซิทีฟโดยอัตโนมัติ ซึ่งจะช่วยให้เห็นภาพรวมทรัพยากร Dependency ของโปรเจ็กต์ได้ชัดเจนยิ่งขึ้น - การมองเห็นการขึ้นต่อกันที่เข้มงวด: ระบบจะแสดงเฉพาะการขึ้นต่อกันโดยตรง เพื่อให้มั่นใจในความถูกต้องและความสามารถในการคาดการณ์
การผสานรวมระบบนิเวศ
- รีจิสทรีกลางของ Bazel: ที่เก็บส่วนกลางสำหรับการค้นหาและจัดการการขึ้นต่อกันทั่วไปเป็นโมzel โมดูล
- การนำโปรเจ็กต์ที่ไม่ใช่ Bazel มาใช้: เมื่อมีการปรับโปรเจ็กต์ที่ไม่ใช่ Bazel (โดยปกติจะเป็นไลบรารี C++ ) ให้ใช้กับ Bazel และเผยแพร่ใน BCR การดำเนินการนี้จะช่วยลดความซับซ้อนในการผสานรวม สำหรับชุมชนทั้งหมด และลดความพยายามที่ซ้ำซ้อนและความขัดแย้งของไฟล์ BUILD ที่กำหนดเอง
- การผสานรวมกับตัวจัดการแพ็กเกจเฉพาะภาษาแบบรวม: ชุดกฎ
ช่วยลดความซับซ้อนในการผสานรวมกับตัวจัดการแพ็กเกจภายนอกสำหรับการขึ้นต่อกันที่ไม่ใช่ Bazel
ซึ่งรวมถึง:
- rules_jvm_external สำหรับ Maven
- rules_python สำหรับ PyPi
- bazel-gazelle สำหรับโมดูล Go
- rules_rust สำหรับ Cargo
ฟีเจอร์ขั้นสูง
- ส่วนขยายโมดูล: ฟีเจอร์
use_repo_ruleและส่วนขยายโมดูลช่วยให้ใช้กฎของที่เก็บที่กำหนดเองและ ตรรกะการแก้ปัญหาได้อย่างยืดหยุ่นเพื่อแนะนำการขึ้นต่อกันที่ไม่ใช่ Bazel bazel modคำสั่ง: คำสั่งย่อยนี้มี วิธีที่มีประสิทธิภาพในการตรวจสอบการขึ้นต่อกันภายนอก คุณจะทราบได้อย่างชัดเจนว่าการขึ้นต่อกันภายนอกมีการกำหนดไว้อย่างไรและมาจากที่ใด- โหมดผู้ให้บริการ: ดึงข้อมูลการขึ้นต่อกันภายนอกที่แน่นอนที่คุณ ต้องการล่วงหน้าเพื่อช่วยให้การบิลด์แบบออฟไลน์ง่ายขึ้น
- ไฟล์ Lockfile: ไฟล์ Lockfile ช่วยปรับปรุงความสามารถในการทำซ้ำบิลด์และเร่งการแก้ปัญหาทรัพยากร Dependency
- (เร็วๆ นี้) การรับรองแหล่งที่มาของ BCR: เสริมความปลอดภัยของซัพพลายเชนด้วยการตรวจสอบแหล่งที่มาของการขึ้นต่อกัน
แนวคิด
ส่วนนี้จะให้รายละเอียดเพิ่มเติมเกี่ยวกับแนวคิดที่เกี่ยวข้องกับการขึ้นต่อกันภายนอก
โมดูล
โปรเจ็กต์ Bazel ที่มีหลายเวอร์ชันได้ โดยแต่ละเวอร์ชันสามารถมีการขึ้นต่อกันกับโมดูลอื่นๆ ได้
ในพื้นที่ทำงาน Bazel ในเครื่อง โมดูลจะแสดงโดยที่เก็บ
ดูรายละเอียดเพิ่มเติมได้ที่ โมดูล Bazel
ที่เก็บ
แผนผังไดเรกทอรีที่มีไฟล์เครื่องหมายขอบเขตที่รูท ซึ่งมีไฟล์ต้นฉบับที่ใช้ได้ในบิลด์ Bazel มักเรียกสั้นๆ ว่า repo
ไฟล์เครื่องหมายขอบเขตของ repo อาจเป็น MODULE.bazel (บ่งบอกว่า repo นี้แสดงโมดูล Bazel), REPO.bazel (ดู ด้านล่าง) หรือในบริบทเดิม WORKSPACE หรือ WORKSPACE.bazel ไฟล์เครื่องหมายขอบเขตของ repo จะระบุขอบเขตของ repo โดยไฟล์ดังกล่าวจะอยู่ในไดเรกทอรีร่วมกันได้หลายไฟล์
ที่เก็บหลัก
ที่เก็บที่กำลังเรียกใช้คำสั่ง Bazel ปัจจุบัน
รูทของที่เก็บหลักเรียกอีกอย่างว่า รูทของพื้นที่ทำงาน
พื้นที่ทำงาน
สภาพแวดล้อมที่คำสั่ง Bazel ทั้งหมดใช้ร่วมกันจะทำงานจากที่เก็บหลักเดียวกัน ซึ่งรวมถึง repo หลักและชุด repo ภายนอกทั้งหมดที่กำหนดไว้
โปรดทราบว่าที่ผ่านมาแนวคิด "ที่เก็บข้อมูล" และ "พื้นที่ทำงาน" มักใช้รวมๆ กัน คำว่า "พื้นที่ทำงาน" มักใช้เพื่ออ้างอิงถึงที่เก็บข้อมูลหลัก และบางครั้งยังใช้เป็นคำพ้องความหมายของ "ที่เก็บข้อมูล" ด้วย
ชื่อที่เก็บ Canonical
ชื่อที่ใช้ระบุที่เก็บได้เสมอ ในบริบทของพื้นที่ทำงาน ที่เก็บแต่ละแห่งจะมีชื่อ Canonical เดียว เป้าหมายภายใน repo ที่มีชื่อ Canonical เป็น canonical_name สามารถระบุได้ด้วยป้ายกำกับ @@canonical_name//package:target (โปรดสังเกต @ 2 ตัว)
ที่เก็บหลักจะมีสตริงว่างเป็นชื่อ Canonical เสมอ
ชื่อที่เก็บที่ปรากฏ
ชื่อที่ใช้ระบุที่เก็บในบริบทของ repo อื่น คุณอาจคิดว่าชื่อนี้เป็น "ชื่อเล่น" ของ repo ก็ได้ เช่น repo ที่มีชื่อ Canonical เป็น michael อาจมีชื่อที่ปรากฏเป็น mike ในบริบทของ repo alice แต่มีชื่อที่ปรากฏเป็น mickey ในบริบทของ repo bob ในกรณีนี้ เป้าหมายภายใน michael สามารถระบุได้ด้วยป้ายกำกับ
@mike//package:target ในบริบทของ alice (โปรดสังเกต @ ตัวเดียว)
ในทางกลับกัน คุณอาจเข้าใจได้ว่าชื่อนี้เป็นการแมปที่เก็บ โดย repo แต่ละแห่ง จะเก็บการแมปจาก "ชื่อที่เก็บที่ปรากฏ" ไปยัง "ชื่อที่เก็บ Canonical"
กฎของที่เก็บ
สคีมาสำหรับคำจำกัดความของที่เก็บข้อมูลที่บอก Bazel ว่าจะแสดงที่เก็บข้อมูลอย่างไร เช่น "ดาวน์โหลดไฟล์เก็บถาวร zip จาก URL ที่ระบุและแตกไฟล์" หรือ "ดึงข้อมูลอาร์ติแฟกต์ Maven ที่ระบุและทำให้พร้อมใช้งานเป็นเป้าหมาย java_import" หรือเพียง "สร้างลิงก์สัญลักษณ์ไปยังไดเรกทอรีในเครื่อง" repo ทุกแห่งจะกำหนด โดยการเรียกใช้กฎของที่เก็บด้วยจำนวนอาร์กิวเมนต์ที่เหมาะสม
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเขียน กฎของที่เก็บของคุณเองได้ที่กฎของที่เก็บ
กฎของที่เก็บที่ใช้กันมากที่สุดคือ
http_archive ซึ่งจะดาวน์โหลดไฟล์เก็บถาวร
จาก URL และแตกไฟล์ และ
local_repository ซึ่งจะสร้างลิงก์สัญลักษณ์ไปยัง
ไดเรกทอรีในเครื่องที่เป็นที่เก็บ Bazel อยู่แล้ว
ดึงข้อมูลที่เก็บ
การดำเนินการทำให้ repo พร้อมใช้งานในดิสก์ในเครื่องโดยการเรียกใช้กฎของที่เก็บที่เชื่อมโยง repo ที่กำหนดไว้ในพื้นที่ทำงานจะไม่พร้อมใช้งานในดิสก์ในเครื่องจนกว่าจะมีการดึงข้อมูล
โดยปกติแล้ว Bazel จะดึงข้อมูล repo ก็ต่อเมื่อต้องการข้อมูลบางอย่างจาก repo และยังไม่ได้ดึงข้อมูล repo นั้น หากมีการดึงข้อมูล repo ไปแล้วก่อนหน้านี้ Bazel จะดึงข้อมูล repo อีกครั้งก็ต่อเมื่อคำจำกัดความของ repo มีการเปลี่ยนแปลง
คุณสามารถใช้คำสั่ง fetch เพื่อเริ่มการดึงข้อมูลล่วงหน้าสำหรับที่เก็บ เป้าหมาย หรือที่เก็บที่จำเป็นทั้งหมดเพื่อทำการบิลด์ ความสามารถนี้ช่วยให้สามารถทำการบิลด์แบบออฟไลน์ได้โดยใช้ตัวเลือก --nofetch
ตัวเลือก --fetch ใช้เพื่อจัดการการเข้าถึงเครือข่าย ค่าเริ่มต้นคือ "จริง"
อย่างไรก็ตาม เมื่อตั้งค่าเป็น "เท็จ" (--nofetch) คำสั่งจะใช้การขึ้นต่อกันเวอร์ชันที่แคชไว้ และหากไม่มีเวอร์ชันที่แคชไว้ คำสั่งจะส่งผลให้เกิดข้อผิดพลาด
ดูข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมการดึงข้อมูลได้ที่ ตัวเลือกการดึงข้อมูล
เลย์เอาต์ไดเรกทอรี
หลังจากดึงข้อมูลแล้ว คุณจะพบ repo ในไดเรกทอรีย่อย external ใน
เอาต์พุตเบสภายใต้ชื่อ Canonical
คุณสามารถเรียกใช้คำสั่งต่อไปนี้เพื่อดูเนื้อหาของ repo ที่มีชื่อ Canonical เป็น canonical_name
ls $(bazel info output_base)/external/ canonical_name ไฟล์ REPO.bazel
ไฟล์ REPO.bazel ใช้เพื่อทำเครื่องหมายขอบเขตบนสุด
ของแผนผังไดเรกทอรีที่เป็น repo ไฟล์นี้ไม่จำเป็นต้องมีเนื้อหาใดๆ เพื่อใช้เป็นไฟล์ขอบเขตของ repo แต่คุณยังใช้ไฟล์นี้เพื่อระบุแอตทริบิวต์ทั่วไปบางอย่างสำหรับเป้าหมายบิลด์ทั้งหมดภายใน repo ได้ด้วย
ไวยากรณ์ของไฟล์ REPO.bazel จะคล้ายกับไฟล์ BUILD ยกเว้นว่าจะไม่รองรับคำสั่ง load ฟังก์ชัน repo() จะใช้อาร์กิวเมนต์เดียวกับฟังก์ชัน package() ในไฟล์ BUILD โดยที่ package()
จะระบุแอตทริบิวต์ทั่วไปสำหรับเป้าหมายบิลด์ทั้งหมดภายในแพ็กเกจ ส่วน repo()
จะทำเช่นเดียวกันสำหรับเป้าหมายบิลด์ทั้งหมดภายใน repo
ตัวอย่างเช่น คุณระบุใบอนุญาตทั่วไปสำหรับเป้าหมายทั้งหมดใน repo ได้โดยใช้ไฟล์ REPO.bazel ต่อไปนี้
repo(
default_package_metadata = ["//:my_license"],
)
ระบบ WORKSPACE เดิม
ใน Bazel เวอร์ชันเก่า (ก่อนเวอร์ชัน 9.0) มีการแนะนำการขึ้นต่อกันภายนอกโดย
การกำหนด repo ในไฟล์ WORKSPACE (หรือ WORKSPACE.bazel) ไฟล์นี้มีไวยากรณ์คล้ายกับไฟล์ BUILD โดยใช้กฎของที่เก็บแทนกฎของบิลด์
ข้อมูลโค้ดต่อไปนี้เป็นตัวอย่างการใช้กฎของที่เก็บ http_archive ในไฟล์ WORKSPACE
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "foo",
urls = ["https://example.com/foo.zip"],
sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)
ข้อมูลโค้ดนี้กำหนด repo ที่มีชื่อ Canonical เป็น foo ในระบบ WORKSPACE โดยค่าเริ่มต้น ชื่อ Canonical ของ repo จะเป็นชื่อที่ปรากฏสำหรับ repo อื่นๆ ทั้งหมดด้วย
ดูรายการทั้งหมดของฟังก์ชันที่ใช้ได้ใน
WORKSPACEไฟล์
ข้อบกพร่องของระบบ WORKSPACE
ในช่วงหลายปีหลังจากการเปิดตัวระบบ WORKSPACE ผู้ใช้ได้รายงานปัญหาต่างๆ มากมาย ซึ่งรวมถึง
- Bazel ไม่ได้ประเมินไฟล์
WORKSPACEของการขึ้นต่อกันใดๆ ดังนั้นจึงต้องกำหนดการขึ้นต่อกันแบบทรานซิทีฟทั้งหมดในไฟล์WORKSPACEของ repo หลัก นอกเหนือจากการขึ้นต่อกันโดยตรง - โปรเจ็กต์ต่างๆ ได้นำรูปแบบ "deps.bzl" มาใช้เพื่อหลีกเลี่ยงปัญหานี้ โดยกำหนดมาโครซึ่งจะกำหนด repo หลายรายการ และขอให้ผู้ใช้เรียกใช้มาโครนี้ในไฟล์
WORKSPACE- ซึ่งก่อให้เกิดปัญหาของตัวเอง เนื่องจากมาโครไม่สามารถ
loadไฟล์.bzlอื่นได้ โปรเจ็กต์เหล่านี้จึงต้องกำหนดการขึ้นต่อกันแบบทรานซิทีฟในมาโคร "deps" นี้ หรือหลีกเลี่ยงปัญหานี้โดยให้ผู้ใช้เรียกใช้มาโคร "deps" แบบหลายเลเยอร์ - Bazel จะประเมินไฟล์
WORKSPACEตามลำดับ นอกจากนี้ การขึ้นต่อกันจะระบุโดยใช้http_archiveกับ URL โดยไม่มีข้อมูลเวอร์ชัน ซึ่งหมายความว่าไม่มีวิธีที่เชื่อถือได้ในการแก้ปัญหาเวอร์ชันในกรณีของการขึ้นต่อกันแบบไดมอนด์ (Aขึ้นต่อกันกับBและCโดยBและCขึ้นต่อกันกับDเวอร์ชันต่างๆ)
- ซึ่งก่อให้เกิดปัญหาของตัวเอง เนื่องจากมาโครไม่สามารถ
เนื่องจากข้อบกพร่องของ WORKSPACE ระบบใหม่ที่อิงตามโมดูล (ชื่อรหัส "Bzlmod") จึงค่อยๆ เข้ามาแทนที่ระบบ WORKSPACE เดิมระหว่าง Bazel เวอร์ชัน 6 ถึง 9 อ่านคำแนะนำในการย้ายข้อมูล Bzlmodเกี่ยวกับวิธีย้ายข้อมูล ไปยัง Bzlmod