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

รายงานปัญหา ดูแหล่งที่มา Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

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

ตั้งแต่ Bazel 6.0 เป็นต้นไป คุณจะจัดการทรัพยากร Dependency ภายนอกด้วย Bazel ได้ 2 วิธี ได้แก่ WORKSPACEระบบแบบเดิมที่เน้นที่รีโป และ MODULE.bazelระบบใหม่ที่เน้นที่โมดูล (มีชื่อรหัสว่า Bzlmod และเปิดใช้ด้วยแฟล็ก --enable_bzlmod) คุณใช้ทั้ง 2 ระบบร่วมกันได้ แต่ Bzlmod จะแทนที่ระบบ WORKSPACE ใน Bazel รุ่นต่อๆ ไป โปรดดูคู่มือการย้ายข้อมูล Bzlmod เกี่ยวกับวิธีย้ายข้อมูล

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

แนวคิด

ที่เก็บ

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

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

ที่เก็บหลัก

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

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

Workspace

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

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

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

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

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

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

ชื่อที่ใช้ในการระบุที่เก็บในบริบทของที่เก็บอื่น คุณอาจคิดว่านี่คือ "ชื่อเล่น" ของที่เก็บ: ที่เก็บที่มีชื่อที่แน่นอน michael อาจมีชื่อที่ปรากฏเป็น mike ในบริบทของที่เก็บ alice แต่ก็อาจมีชื่อที่ปรากฏเป็น mickey ในบริบทของที่เก็บ bob ในกรณีนี้ เป้าหมายภายใน michael สามารถระบุได้ด้วยป้ายกำกับ @mike//pac/kage: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.bazel จะคล้ายกับไฟล์ BUILD ยกเว้นว่าจะไม่รองรับคำสั่ง load และมีเพียงฟังก์ชันเดียวคือ repo() repo() มีอาร์กิวเมนต์เดียวกันกับpackage() ฟังก์ชันในไฟล์ BUILD ในขณะที่ package() ระบุแอตทริบิวต์ทั่วไปสำหรับเป้าหมายการสร้างทั้งหมดภายในแพ็กเกจ repo() จะทำเช่นเดียวกันสำหรับเป้าหมายการสร้างทั้งหมดภายในที่เก็บ

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

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

จัดการทรัพยากร Dependency ภายนอกด้วย Bzlmod

Bzlmod ซึ่งเป็นระบบย่อยของการอ้างอิงภายนอกใหม่จะใช้กับคำจำกัดความของที่เก็บโดยตรงไม่ได้ แต่จะสร้างกราฟการขึ้นต่อกันจากโมดูล เรียกใช้ส่วนขยายที่ด้านบนของกราฟ และกำหนด repo ตามนั้น

โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน แต่ละเวอร์ชันจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่ขึ้นอยู่กับโมดูลนั้น โมดูลต้องมีไฟล์ 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")

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

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

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

กำหนดที่เก็บด้วย WORKSPACE

ในอดีต คุณสามารถจัดการการอ้างอิงภายนอกได้โดยการกำหนดที่เก็บข้อมูลในไฟล์ 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 รุ่นต่อๆ ไป โปรดอ่านคำแนะนำในการย้ายข้อมูล Bzlmod เพื่อดูวิธีย้ายข้อมูลไปยัง Bzlmod