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
ลิงก์ภายนอกใน Bzlmod
- ตัวอย่างการใช้งาน Bzlmod ใน bazelbuild/examples
- การยกเครื่องการอ้างอิงภายนอกของ Bazel (เอกสารการออกแบบ Bzlmod ต้นฉบับ)
- การพูดคุยเกี่ยวกับ Bzlmod ใน BazelCon 2021
- การพูดคุยในวันชุมชน Bazel เกี่ยวกับ Bzlmod
กำหนดที่เก็บด้วย 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