ภาพรวมของทรัพยากร Dependency ภายนอก

Bazel รองรับการขึ้นต่อกันภายนอก ไฟล์ต้นฉบับ (ทั้งข้อความและไบนารี) ที่ใช้ ในบิลด์ซึ่งไม่ได้มาจากพื้นที่ทำงาน เช่น อาจเป็นชุดกฎที่โฮสต์ในที่เก็บ GitHub, อาร์ติแฟกต์ Maven หรือไดเรกทอรีในเครื่องของคุณนอกพื้นที่ทำงานปัจจุบัน

เอกสารนี้จะให้ภาพรวมของระบบก่อนที่จะพิจารณาแนวคิดบางอย่าง ในรายละเอียดเพิ่มเติม

ภาพรวมของระบบ

ระบบการอ้างอิงภายนอกของ 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 จะค้นหาโมดูลการขึ้นต่อกันแบบทรานซิทีฟทั้งหมดในรีจิสทรี Bazel ซึ่งโดยค่าเริ่มต้นคือรีจิสทรีกลางของ Bazel รีจิสทรีมีMODULE.bazelไฟล์ของการอ้างอิง ซึ่งช่วยให้ Bazel ค้นพบกราฟการอ้างอิงแบบทรานซิทีฟทั้งหมดก่อนที่จะทำการแก้ปัญหาเวอร์ชัน

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

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

ที่เก็บข้อมูล 3 ประเภท ได้แก่ ที่เก็บข้อมูลหลัก (ซึ่งเป็นโครงสร้างแหล่งที่มาที่คุณกำลังทำงานอยู่) ที่เก็บข้อมูลที่แสดงโมดูลการขึ้นต่อกันแบบทรานซิทีฟ และที่เก็บข้อมูลที่สร้างขึ้นโดยส่วนขยายของโมดูล จะรวมกันเป็นพื้นที่ทำงาน ระบบจะดึงข้อมูลที่เก็บภายนอก (ที่เก็บที่ไม่ใช่ที่เก็บหลัก) ตามต้องการ เช่น เมื่อมีการอ้างอิงที่เก็บเหล่านั้นโดยป้ายกำกับ (เช่น @repo//pkg:target) ในไฟล์ BUILD

ข้อดี

ระบบการขึ้นต่อกันภายนอกของ Bazel มีประโยชน์มากมาย

การแก้ปัญหาการขึ้นต่อกันโดยอัตโนมัติ

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

การผสานรวมระบบนิเวศ

  • รีจิสทรีกลางของ Bazel: ที่เก็บข้อมูลส่วนกลางสำหรับค้นหาและจัดการการอ้างอิงทั่วไปเป็นโมดูล Bazel
  • การนำโปรเจ็กต์ที่ไม่ใช่ Bazel มาใช้: เมื่อมีการปรับโปรเจ็กต์ที่ไม่ใช่ Bazel (โดยปกติคือไลบรารี C++) ให้ใช้กับ Bazel และพร้อมใช้งานใน BCR ก็จะช่วยให้การผสานรวมโปรเจ็กต์ดังกล่าวสำหรับทั้งชุมชนเป็นไปอย่างราบรื่น รวมถึงช่วยลดความพยายามที่ซ้ำซ้อนและข้อขัดแย้งของไฟล์ BUILD ที่กำหนดเอง
  • การผสานรวมแบบรวมกับเครื่องมือจัดการแพ็กเกจเฉพาะภาษา: ชุดกฎ ช่วยลดความซับซ้อนในการผสานรวมกับเครื่องมือจัดการแพ็กเกจภายนอกสำหรับทรัพยากร Dependency ที่ไม่ใช่ Bazel ซึ่งรวมถึง

ฟีเจอร์ขั้นสูง

  • ส่วนขยายโมดูล: ฟีเจอร์ use_repo_rule และส่วนขยายโมดูล ช่วยให้ใช้กฎที่กำหนดเองของที่เก็บและ ตรรกะการแก้ปัญหาได้อย่างยืดหยุ่นเพื่อนำเข้าการอ้างอิงที่ไม่ใช่ Bazel
  • bazel mod Command: คำสั่งย่อยมีวิธีที่มีประสิทธิภาพในการตรวจสอบทรัพยากร Dependency ภายนอก คุณทราบอย่างชัดเจนว่ามีการกำหนดการอ้างอิงภายนอกอย่างไรและมาจากที่ใด
  • โหมดผู้ให้บริการ: ดึงข้อมูลการอ้างอิงภายนอกที่แน่นอนล่วงหน้า ซึ่งคุณต้องใช้เพื่ออำนวยความสะดวกในการสร้างแบบออฟไลน์
  • ไฟล์ล็อก: ไฟล์ล็อกช่วยปรับปรุงความสามารถในการสร้างซ้ำและ เร่งการแก้ปัญหาการอ้างอิง
  • (เร็วๆ นี้) การรับรองแหล่งที่มาของ BCR: เสริมความแข็งแกร่งด้านความปลอดภัยของซัพพลายเชนด้วยการตรวจสอบแหล่งที่มาที่ยืนยันแล้วของ การอ้างอิง

แนวคิด

ส่วนนี้จะให้รายละเอียดเพิ่มเติมเกี่ยวกับแนวคิดที่เกี่ยวข้องกับการอ้างอิงภายนอก

โมดูล

โปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน โดยแต่ละเวอร์ชันอาจมี การอ้างอิงโมดูลอื่นๆ

ในพื้นที่ทำงาน Bazel ในเครื่อง โมดูลจะแสดงโดยที่เก็บ

ดูรายละเอียดเพิ่มเติมได้ที่โมดูล Bazel

ที่เก็บ

แผนผังไดเรกทอรีที่มีไฟล์เครื่องหมายขอบเขตที่รูท ซึ่งมีไฟล์ต้นฉบับที่ใช้ได้ในบิลด์ Bazel มักเรียกสั้นๆ ว่า repo

ไฟล์เครื่องหมายขอบเขตของ repo อาจเป็น MODULE.bazel (บ่งบอกว่า repo นี้แสดงโมดูล Bazel), REPO.bazel (ดูด้านล่าง) หรือในบริบทเดิม WORKSPACE หรือ WORKSPACE.bazel ไฟล์เครื่องหมายขอบเขตของ repo จะระบุขอบเขตของ repo โดยไฟล์ดังกล่าวจะอยู่ในไดเรกทอรีร่วมกันได้หลายไฟล์

ที่เก็บหลัก

ที่เก็บที่กำลังเรียกใช้คำสั่ง Bazel ปัจจุบัน

รูทของที่เก็บหลักยังเรียกว่ารูทของพื้นที่ทำงานด้วย

Workspace

สภาพแวดล้อมที่คำสั่ง Bazel ทั้งหมดใช้ร่วมกันจะทำงานในที่เก็บหลักเดียวกัน โดยจะครอบคลุมที่เก็บหลักและชุดที่เก็บภายนอกทั้งหมดที่กำหนด

โปรดทราบว่าที่ผ่านมาแนวคิด "ที่เก็บข้อมูล" และ "พื้นที่ทำงาน" มักใช้รวมๆ กัน คำว่า "พื้นที่ทำงาน" มักใช้เพื่ออ้างอิงถึงที่เก็บข้อมูลหลัก และบางครั้งยังใช้เป็นคำพ้องความหมายของ "ที่เก็บข้อมูล" ด้วย

ชื่อที่เก็บ Canonical

ชื่อที่ใช้ในการระบุที่เก็บเสมอ ในบริบทของเวิร์กสเปซ ที่เก็บข้อมูลแต่ละรายการจะมีชื่อมาตรฐานเพียงชื่อเดียว เป้าหมายภายในที่เก็บ ซึ่งมีชื่อ Canonical เป็น canonical_name สามารถระบุได้ด้วยป้ายกำกับ @@canonical_name//package:target (โปรดสังเกต @ สองตัว)

ที่เก็บหลักจะมีสตริงว่างเป็นชื่อที่แน่นอนเสมอ

ชื่อที่เก็บที่เห็น

ชื่อที่ใช้ระบุที่เก็บในบริบทของที่เก็บอื่น คุณอาจคิดว่านี่คือ "ชื่อเล่น" ของที่เก็บได้ ที่เก็บที่มีชื่อมาตรฐาน michael อาจมีชื่อที่ปรากฏเป็น mike ในบริบทของที่เก็บ alice แต่ก็อาจมีชื่อที่ปรากฏเป็น mickey ในบริบทของที่เก็บ bob ในกรณีนี้ เป้าหมายภายใน michael สามารถระบุได้ด้วยป้ายกำกับ @mike//package:target ในบริบทของ alice (โปรดสังเกต @ เดียว)

ในทางกลับกัน คุณสามารถเข้าใจได้ว่านี่คือการแมปที่เก็บ: ที่เก็บแต่ละแห่ง จะรักษาการแมปจาก "ชื่อที่เก็บที่ปรากฏ" ไปยัง "ชื่อที่เก็บที่แน่นอน"

กฎที่เก็บ

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเขียนกฎของที่เก็บได้ที่กฎของที่เก็บ

กฎของ repo ที่พบบ่อยที่สุดคือ http_archive ซึ่งจะดาวน์โหลดไฟล์เก็บถาวรจาก URL และแตกไฟล์ และ local_repository ซึ่งจะสร้างลิงก์สัญลักษณ์ไปยังไดเรกทอรีในเครื่องที่เป็นที่เก็บ Bazel อยู่แล้ว

ดึงข้อมูลที่เก็บ

การดำเนินการทำให้ที่เก็บพร้อมใช้งานในดิสก์ในเครื่องโดยการเรียกใช้กฎที่เก็บที่เชื่อมโยง ที่เก็บที่กำหนดไว้ในพื้นที่ทำงานจะไม่พร้อมใช้งานในฮาร์ดดิสก์ ก่อนที่จะมีการดึงข้อมูล

โดยปกติแล้ว Bazel จะดึงข้อมูลที่เก็บก็ต่อเมื่อต้องการบางอย่างจากที่เก็บ และยังไม่ได้ดึงข้อมูลที่เก็บ หากดึงข้อมูลที่เก็บมาก่อนแล้ว Bazel จะดึงข้อมูลอีกครั้งก็ต่อเมื่อคำจำกัดความมีการเปลี่ยนแปลง

คำสั่ง fetch สามารถใช้เพื่อเริ่มการดึงข้อมูลล่วงหน้าสำหรับที่เก็บ เป้าหมาย หรือที่เก็บที่จำเป็นทั้งหมดเพื่อทำการสร้าง ความสามารถนี้ ช่วยให้สร้างแบบออฟไลน์ได้โดยใช้ตัวเลือก --nofetch

--fetch ตัวเลือกนี้ใช้เพื่อจัดการการเข้าถึงเครือข่าย ค่าเริ่มต้นคือ True อย่างไรก็ตาม เมื่อตั้งค่าเป็น false (--nofetch) คำสั่งจะใช้เวอร์ชันที่แคชไว้ของ Dependency และหากไม่มี คำสั่งจะทำงานไม่สำเร็จ

ดูข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมการดึงข้อมูลได้ที่ตัวเลือกการดึงข้อมูล

เลย์เอาต์ไดเรกทอรี

หลังจากดึงข้อมูลแล้ว คุณจะพบที่เก็บในไดเรกทอรีย่อย external ในเอาต์พุตเบสภายใต้ชื่อ Canonical

คุณเรียกใช้คำสั่งต่อไปนี้เพื่อดูเนื้อหาของที่เก็บด้วยชื่อที่แน่นอน canonical_name ได้

ls $(bazel info output_base)/external/ canonical_name 

ไฟล์ REPO.bazel

ไฟล์ REPO.bazel ใช้เพื่อทำเครื่องหมายขอบเขตบนสุด ของโครงสร้างไดเรกทอรีที่ประกอบกันเป็นที่เก็บ ไฟล์นี้ไม่จำเป็นต้องมีเนื้อหาใดๆ เพื่อใช้เป็นไฟล์ขอบเขตของ repo แต่ก็สามารถใช้เพื่อระบุแอตทริบิวต์ทั่วไปบางอย่างสำหรับเป้าหมายการสร้างทั้งหมดภายใน repo ได้เช่นกัน

ไวยากรณ์ของไฟล์ REPO.bazel คล้ายกับไฟล์ BUILD ยกเว้นว่าจะไม่รองรับคำสั่ง load ฟังก์ชัน repo() จะใช้อาร์กิวเมนต์เดียวกันกับpackage() ฟังก์ชันในไฟล์ BUILD ในขณะที่ package() ระบุแอตทริบิวต์ทั่วไปสำหรับเป้าหมายการสร้างทั้งหมดภายในแพ็กเกจ repo() จะทำเช่นเดียวกันสำหรับเป้าหมายการสร้างทั้งหมดภายในที่เก็บ

เช่น คุณสามารถระบุใบอนุญาตทั่วไปสำหรับเป้าหมายทั้งหมดในที่เก็บได้โดย มีไฟล์ REPO.bazel ดังนี้

repo(
    default_package_metadata = ["//:my_license"],
)

ระบบ WORKSPACE เดิม

ใน Bazel เวอร์ชันเก่า (ก่อน 9.0) มีการนำทรัพยากร Dependency ภายนอกมาใช้โดยการกำหนด repo ในไฟล์ WORKSPACE (หรือ WORKSPACE.bazel) ไฟล์นี้มีไวยากรณ์คล้ายกับไฟล์ BUILD โดยใช้กฎ repo แทนกฎการสร้าง

ข้อมูลโค้ดต่อไปนี้เป็นตัวอย่างการใช้กฎ http_archive repo ในไฟล์ WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "foo",
    urls = ["https://example.com/foo.zip"],
    sha256 = "c9526390a7cd420fdcec2988b4f3626fe9c5b51e2959f685e8f4d170d1a9bd96",
)

ข้อมูลโค้ดจะกำหนดที่เก็บที่มีชื่อ Canonical เป็น foo ในWORKSPACE ระบบ ชื่อ Canonical ของที่เก็บจะยังเป็นชื่อที่ปรากฏของที่เก็บนั้นต่อ ที่เก็บอื่นๆ ทั้งหมดด้วยโดยค่าเริ่มต้น

ดูรายการทั้งหมดของฟังก์ชันที่พร้อมใช้งานในไฟล์ WORKSPACE

ข้อบกพร่องของระบบ WORKSPACE

ในช่วงหลายปีหลังจากเปิดตัวWORKSPACEระบบ ผู้ใช้รายงานปัญหาต่างๆ มากมาย ซึ่งรวมถึง

  • Bazel ไม่ได้ประเมินไฟล์ WORKSPACE ของการอ้างอิงใดๆ ดังนั้นการอ้างอิงแบบทรานซิทีฟทั้งหมดต้องกำหนดไว้ในไฟล์ WORKSPACE ของที่เก็บหลัก นอกเหนือจากการอ้างอิงโดยตรง
  • โปรเจ็กต์จึงใช้รูปแบบ "deps.bzl" เพื่อหลีกเลี่ยงปัญหานี้ โดยจะกำหนดมาโครซึ่งจะกำหนดที่เก็บหลายรายการ และขอให้ผู้ใช้เรียกใช้มาโครนี้ในไฟล์ WORKSPACE
    • ซึ่งก็มีปัญหาของมันเอง นั่นคือมาโครไม่สามารถloadไฟล์.bzlอื่นๆ ได้ ดังนั้น โปรเจ็กต์เหล่านี้จึงต้องกำหนดการอ้างอิงแบบทรานซิทีฟในมาโคร "deps" นี้ หรือแก้ไขปัญหานี้โดยให้ผู้ใช้เรียกใช้มาโคร "deps" แบบหลายเลเยอร์
    • Bazel จะประเมินไฟล์ WORKSPACE ตามลำดับ นอกจากนี้ คุณยังระบุ การอ้างอิงได้โดยใช้ http_archive กับ URL โดยไม่ต้องระบุ ข้อมูลเวอร์ชัน ซึ่งหมายความว่าไม่มีวิธีที่เชื่อถือได้ในการระบุเวอร์ชันในกรณีของการอ้างอิงแบบไดมอนด์ (A ขึ้นอยู่กับ B และ C; B และ C ต่างก็ขึ้นอยู่กับ D เวอร์ชันที่แตกต่างกัน)

เนื่องจากข้อบกพร่องของ WORKSPACE ระบบใหม่ที่อิงตามโมดูล (มีชื่อรหัสว่า "Bzlmod") จึงค่อยๆ เข้ามาแทนที่ระบบ WORKSPACE เดิมระหว่าง Bazel 6 ถึง 9 อ่านคำแนะนำในการย้ายข้อมูล Bzlmod เกี่ยวกับวิธีย้ายข้อมูล ไปยัง Bzlmod