Bazel รองรับทรัพยากรภายนอก ซึ่งเป็นไฟล์ต้นฉบับ (ทั้งแบบข้อความและแบบไบนารี) ที่ใช้ในการสร้างที่ไม่ได้มาจากเวิร์กスペース เช่น อาจเป็นชุดกฎที่โฮสต์อยู่ในที่เก็บ GitHub, อาร์ติแฟกต์ Maven หรือไดเรกทอรีในเครื่องคอมพิวเตอร์ของคุณซึ่งอยู่นอกเวิร์กスペースปัจจุบัน
ตั้งแต่ Bazel 6.0 เป็นต้นไป คุณจะจัดการการพึ่งพาภายนอกด้วย Bazel ได้ 2 วิธี ได้แก่ ระบบ WORKSPACE
แบบดั้งเดิมที่เน้นที่ที่เก็บ และระบบ MODULE.bazel
แบบใหม่ซึ่งเน้นที่โมดูล (ชื่อรหัส Bzlmod และเปิดใช้ด้วย Flag --enable_bzlmod
) คุณใช้ทั้ง 2 ระบบร่วมกันได้ แต่ Bzlmod จะเข้ามาแทนที่ระบบ WORKSPACE
ในรุ่น Bazel ในอนาคต โปรดดูคำแนะนำในการย้ายข้อมูล Bzlmod เกี่ยวกับวิธีย้ายข้อมูล
เอกสารนี้อธิบายแนวคิดเกี่ยวกับการจัดการทรัพยากรภายนอกใน Bazel ก่อนอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับระบบทั้ง 2 ระบบ
แนวคิด
ที่เก็บ
ต้นไม้ไดเรกทอรีที่มีไฟล์เครื่องหมายขอบเขตที่รูท ซึ่งมีไฟล์ต้นฉบับที่ใช้ได้ในบิลด์ Bazel มักย่อเป็น repo
ไฟล์เครื่องหมายขอบเขตของ repo อาจเป็น MODULE.bazel
(บ่งบอกว่า repo นี้แสดงโมดูล Bazel) REPO.bazel
(ดูด้านล่าง) หรือในบริบทเดิม WORKSPACE
หรือ WORKSPACE.bazel
ไฟล์เครื่องหมายขอบเขตของรีโปจะระบุขอบเขตของรีโป โดยไฟล์ดังกล่าวจะอยู่ในไดเรกทอรีได้หลายไฟล์
ที่เก็บหลัก
พื้นที่เก็บข้อมูลที่กําลังเรียกใช้คําสั่ง Bazel อยู่
Workspace
สภาพแวดล้อมที่คำสั่ง Bazel ทั้งหมดใช้ร่วมกันจะทำงานในที่เก็บข้อมูลหลักเดียวกัน
โปรดทราบว่าที่ผ่านมาแนวคิด "ที่เก็บข้อมูล" และ "เวิร์กスペース" มักสับสนกัน คำว่า "เวิร์กスペース" มักใช้เพื่ออ้างอิงถึงที่เก็บข้อมูลหลัก และบางครั้งยังใช้เป็นคำพ้องความหมายของ "ที่เก็บข้อมูล" ด้วย
ชื่อที่เก็บ Canonical
ชื่อ Canonical ที่ระบุที่เก็บได้ ในบริบทของที่ทำงาน พื้นที่เก็บข้อมูลแต่ละแห่งจะมีชื่อตามหลักเกณฑ์เพียงชื่อเดียว เป้าหมายภายในที่เก็บซึ่งมีชื่อ Canonical เป็น canonical_name
จะเข้าถึงได้ด้วยป้ายกำกับ @@canonical_name//pac/kage:target
(โปรดสังเกต @
2 ตัว)
ที่เก็บหลักจะมีสตริงว่างเป็นชื่อตามแบบฉบับเสมอ
ชื่อที่เก็บที่ปรากฏ
ชื่อที่เก็บที่ใช้อ้างอิงได้ในบริบทของที่เก็บอื่น
คุณสามารถมองชื่อนี้ว่าเป็น "ชื่อเล่น" ของรีโป: รีโปที่มีชื่อตามหลักเกณฑ์
michael
อาจมีชื่อที่ปรากฏเป็น mike
ในบริบทของรีโป
alice
แต่อาจมีชื่อที่ปรากฏเป็น mickey
ในบริบทของรีโป
bob
ในกรณีนี้ เป้าหมายภายใน michael
สามารถเข้าถึงได้ด้วยป้ายกำกับ
@mike//pac/kage:target
ในบริบทของ alice
(โปรดสังเกต @
ตัวเดียว)
หรือจะเข้าใจว่าการแมปที่เก็บก็ได้ โดยที่แต่ละที่เก็บจะรักษาการแมปจาก "ชื่อที่เก็บที่ปรากฏ" ไปยัง "ชื่อที่เก็บตามหลักเกณฑ์"
กฎที่เก็บ
สคีมาสำหรับคำจำกัดความของที่เก็บข้อมูลที่บอก Bazel เกี่ยวกับวิธีสร้างที่เก็บข้อมูล เช่น "ดาวน์โหลดไฟล์ ZIP จาก URL บางรายการและแตกไฟล์" หรือ "ดึงข้อมูลอาร์ติแฟกต์ Maven บางรายการและทำให้พร้อมใช้งานเป็นเป้าหมาย java_import
" หรือเพียงแค่ "ลิงก์สัญลักษณ์ไดเรกทอรีในเครื่อง" รีโปทุกรายการจะกำหนดโดยการเรียกใช้กฎรีโปที่มีอาร์กิวเมนต์ในจำนวนที่เหมาะสม
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเขียนกฎของที่เก็บข้อมูลของคุณเองได้ที่กฎของที่เก็บข้อมูล
กฎที่ใช้กับรีโพซิทอรีที่พบบ่อยที่สุดคือ http_archive
ซึ่งจะดาวน์โหลดไฟล์เก็บถาวรจาก URL และแตกไฟล์ และ local_repository
ซึ่งจะลิงก์ไดเรกทอรีในเครื่องที่เป็นรีโพซิทอรี Bazel อยู่แล้ว
ดึงข้อมูลที่เก็บ
การดำเนินการทําให้รีโปพร้อมใช้งานในดิสก์ในเครื่องโดยการเรียกใช้กฎรีโปที่เกี่ยวข้อง รีโพซิทอรีที่กําหนดไว้ในเวิร์กสเปซจะไม่พร้อมใช้งานในดิสก์ในเครื่องก่อนที่จะมีการดึงข้อมูล
โดยปกติแล้ว Bazel จะดึงข้อมูลรีโปก็ต่อเมื่อต้องการข้อมูลจากรีโปนั้น และยังไม่ได้ดึงข้อมูลรีโปนั้น หากดึงข้อมูลรีโปไปแล้วก่อนหน้านี้ Bazel จะดึงข้อมูลอีกครั้งก็ต่อเมื่อคําจํากัดความของรีโปมีการเปลี่ยนแปลงเท่านั้น
คุณสามารถใช้คำสั่ง fetch
เพื่อเริ่มการดึงข้อมูลล่วงหน้าสำหรับที่เก็บ เป้าหมาย หรือที่เก็บที่จำเป็นทั้งหมดเพื่อทำการบิลด์ ความสามารถนี้ทำให้สร้างแบบออฟไลน์ได้โดยใช้ตัวเลือก --nofetch
ตัวเลือก --fetch
มีไว้เพื่อจัดการการเข้าถึงเครือข่าย ค่าเริ่มต้นคือ "จริง"
อย่างไรก็ตาม เมื่อตั้งค่าเป็นเท็จ (--nofetch
) คำสั่งจะใช้เวอร์ชันของข้อกำหนดซึ่งแคชไว้ หากไม่มี คำสั่งจะดำเนินการไม่สำเร็จ
ดูข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมการดึงข้อมูลได้ที่ตัวเลือกการดึงข้อมูล
เลย์เอาต์ไดเรกทอรี
หลังจากดึงข้อมูลแล้ว คุณจะเห็นที่เก็บในไดเรกทอรีย่อย 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 โดยตรงไม่ได้ แต่ระบบจะสร้างกราฟทรัพยากร Dependency จากโมดูล เรียกใช้ส่วนขยายบนกราฟ และกำหนดที่เก็บตามลำดับ
โมดูล Bazel คือโปรเจ็กต์ Bazel ที่มีได้หลายเวอร์ชัน โดยแต่ละเวอร์ชันจะเผยแพร่ข้อมูลเมตาเกี่ยวกับโมดูลอื่นๆ ที่ใช้ร่วมกัน โมดูลต้องมีไฟล์ MODULE.bazel
ที่รูทของรีโป ข้างไฟล์ WORKSPACE
ไฟล์นี้เป็นไฟล์ Manifest ของโมดูล ซึ่งจะประกาศชื่อ เวอร์ชัน รายการของสิ่งที่ต้องพึ่งพา และข้อมูลอื่นๆ ตัวอย่างเบื้องต้นมีดังนี้
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 Central
Registry รีจิสทรีจะมีไฟล์ MODULE.bazel
ของข้อกําหนด ซึ่งช่วยให้ Bazel ค้นพบกราฟข้อกําหนดแบบทรานซิทีฟทั้งหมดก่อนที่จะทำการแก้ไขเวอร์ชัน
หลังจากการแก้ไขเวอร์ชันซึ่งจะเลือกเวอร์ชันเดียวสำหรับแต่ละโมดูลแล้ว
Bazel จะปรึกษารีจิสทรีอีกครั้งเพื่อดูวิธีกำหนดที่เก็บสำหรับแต่ละโมดูล (ในกรณีส่วนใหญ่จะใช้ http_archive
)
โมดูลยังระบุข้อมูลที่กำหนดเองที่เรียกว่าแท็กได้ด้วย ซึ่งส่วนขยายโมดูลจะใช้หลังจากการแก้ไขโมดูลเพื่อกำหนดที่เก็บข้อมูลเพิ่มเติม ส่วนขยายเหล่านี้มีความสามารถคล้ายกับกฎของรีโป ซึ่งช่วยให้ดำเนินการต่างๆ ได้ เช่น I/O ของไฟล์และการส่งคำขอเครือข่าย นอกเหนือจากการดำเนินการอื่นๆ แล้ว โมดูลเหล่านี้ยังช่วยให้ Bazel โต้ตอบกับระบบการจัดการแพ็กเกจอื่นๆ ได้ ขณะเดียวกันก็เคารพกราฟความเกี่ยวข้องที่สร้างขึ้นจากโมดูล Bazel ด้วย
ลิงก์ภายนอกใน Bzlmod
- ตัวอย่างการใช้ Bzlmod ใน bazelbuild/examples
- การปรับปรุงการพึ่งพาภายนอกของ Bazel (เอกสารการออกแบบ Bzlmod ฉบับแรก)
- การบรรยายเกี่ยวกับ Bzlmod ใน BazelCon 2021
- การบรรยายเกี่ยวกับ Bzlmod ในงาน Bazel Community Day
กำหนดที่เก็บด้วย WORKSPACE
ก่อนหน้านี้ คุณสามารถจัดการการอ้างอิงภายนอกได้โดยกำหนดที่เก็บในไฟล์ 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",
)
ข้อมูลโค้ดจะกำหนดที่เก็บซึ่งมีชื่อตามหลักเกณฑ์เป็น 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 เราจึงจะแทนที่ระบบ WORKSPACE รุ่นเดิมด้วย Bzlmod ใน Bazel รุ่นต่อๆ ไป โปรดอ่านคำแนะนำในการย้ายข้อมูล Bzlmod เกี่ยวกับวิธีย้ายข้อมูลไปยัง Bzlmod