Bazel รองรับทรัพยากร Dependency ภายนอก ไฟล์ต้นฉบับ (ทั้งข้อความและไบนารี) ที่ใช้ในบิลด์ที่ไม่ได้มาจากพื้นที่ทำงาน เช่น อาจเป็นชุดกฎที่โฮสต์ในที่เก็บ GitHub, อาร์ติแฟกต์ Maven หรือไดเรกทอรีในเครื่องภายในที่อยู่นอกพื้นที่ทำงานปัจจุบัน
การจัดการทรัพยากร Dependency ภายนอกด้วย Bazel จาก Bazel 6.0 มีอยู่ 2 วิธีด้วยกัน ได้แก่ ระบบ WORKSPACE
แบบดั้งเดิมที่มุ่งเน้นที่เก็บ และระบบ MODULE.bazel
แบบใหม่ที่เน้นโมดูล (รหัสชื่อว่า Bzlmod
และเปิดใช้ด้วยแฟล็ก --enable_bzlmod
) คุณสามารถใช้ทั้ง 2 ระบบร่วมกันได้ แต่ Bzlmod} จะมาแทนที่ระบบ WORKSPACE
ใน Bazel ในอนาคต {/1
เอกสารนี้อธิบายแนวคิดเกี่ยวกับการจัดการทรัพยากร Dependency ภายนอกใน Bazel ก่อนที่จะลงรายละเอียดเกี่ยวกับระบบทั้ง 2 ระบบนี้เพิ่มเติม
แนวคิด
ที่เก็บ
แผนผังไดเรกทอรีที่มีไฟล์ตัวทำเครื่องหมายขอบเขตอยู่ที่รูท มีไฟล์แหล่งที่มาซึ่งใช้ในการสร้างบิลด์ Bazel ได้ มักจะย่อให้เหลือเพียงที่เก็บ
ไฟล์ตัวทำเครื่องหมายขอบเขตของที่เก็บอาจ MODULE.bazel
(เป็นสัญญาณว่าที่เก็บนี้แทนโมดูล Bazel), REPO.bazel
(ดูด้านล่าง) หรือในบริบทเดิม WORKSPACE
หรือ WORKSPACE.bazel
ไฟล์ตัวทำเครื่องหมายขอบเขตที่เก็บใดก็ตามจะแสดงขอบเขตของที่เก็บ โดยไฟล์เหล่านี้หลายๆ ไฟล์สามารถอยู่ร่วมกันได้ในไดเรกทอรี
ที่เก็บหลัก
ที่เก็บที่มีการเรียกใช้คำสั่ง Bazel ปัจจุบัน
Workspace
สภาพแวดล้อมที่แชร์โดยคำสั่ง Bazel ทั้งหมดจะทำงานในที่เก็บหลักเดียวกัน
โปรดทราบว่าที่ผ่านมาแนวคิดของ "ที่เก็บ" และ "พื้นที่ทำงาน" จะรวมอยู่ด้วยกัน คำว่า "พื้นที่ทำงาน" มักใช้เพื่ออ้างถึงที่เก็บหลัก และบางครั้งยังใช้เป็นคำพ้องความหมายของ "ที่เก็บ" ด้วย
ชื่อที่เก็บ Canonical
ชื่อ Canonical ที่ที่เก็บระบุที่อยู่ได้ ภายในบริบทของพื้นที่ทำงาน ที่เก็บแต่ละรายการจะมีชื่อ Canonical ชื่อเดียว เป้าหมายภายในที่เก็บที่ชื่อ Canonical คือ canonical_name
จะระบุด้วยป้ายกำกับ @@canonical_name//pac/kage:target
ได้ (โปรดสังเกต @
คู่)
ที่เก็บหลักจะมีสตริงว่างเป็นชื่อ Canonical เสมอ
ชื่อที่เก็บที่ชัดเจน
ชื่อที่เก็บระบุที่อยู่ได้ในบริบทของที่เก็บอื่น
อาจคิดว่าเป็น "ชื่อเล่น" ของที่เก็บ ที่เก็บที่มีชื่อ Canonical michael
อาจมีชื่อที่เห็นได้ชัดเป็น mike
ในบริบทของที่เก็บ alice
แต่อาจมีชื่อที่ชัดเจนว่า mickey
ในบริบทของที่เก็บ bob
ในกรณีนี้ เป้าหมายภายใน michael
จะแก้ไขได้ด้วยป้ายกำกับ @mike//pac/kage:target
ในบริบทของ alice
(โปรดระบุ @
เดี่ยว)
ในทางกลับกัน อาจเข้าใจได้ว่าเป็นการแมปที่เก็บ ที่เก็บแต่ละรายการจะดูแลรักษาการแมปจาก "ชื่อที่เก็บที่ปรากฏ" ไปยัง "ชื่อที่เก็บ Canonical"
กฎที่เก็บ
สคีมาของคำจำกัดความของที่เก็บซึ่งบอก Bazel ถึงวิธีการทำให้ที่เก็บเป็นรูปธรรม เช่น อาจเป็น "ดาวน์โหลดไฟล์เก็บถาวร Zip จาก URL หนึ่งๆ และดึงข้อมูล" หรือ "ดึงข้อมูลอาร์ติแฟกต์ Maven บางรายการและทำให้พร้อมใช้งานเป็นเป้าหมาย java_import
" หรือเพียงแค่ "ลิงก์สัญลักษณ์ไดเรกทอรีในเครื่อง" ทุกที่เก็บจะกำหนดโดยการเรียกใช้กฎที่เก็บที่มีจำนวนอาร์กิวเมนต์ที่เหมาะสม
ดูกฎที่เก็บเพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีเขียนกฎที่เก็บของคุณเอง
กฎที่เก็บที่พบบ่อยที่สุดในปัจจุบันคือ http_archive
ซึ่งจะดาวน์โหลดไฟล์ที่เก็บถาวรจาก URL แล้วดึงข้อมูล และ local_repository
ซึ่งจะลิงก์ไดเรกทอรีในเครื่องซึ่งเป็นที่เก็บ Bazel อยู่แล้ว
ดึงข้อมูลที่เก็บ
การดำเนินการทำให้ที่เก็บพร้อมใช้งานในดิสก์ภายในโดยการเรียกใช้กฎที่เก็บที่เชื่อมโยง ที่เก็บที่กำหนดไว้ในพื้นที่ทำงานไม่พร้อมใช้งานบนดิสก์ในเครื่องก่อนที่จะมีการดึงข้อมูล
โดยปกติ Bazel จะดึงข้อมูลที่เก็บก็ต่อเมื่อต้องการบางอย่างจากที่เก็บเท่านั้น และที่เก็บยังไม่ได้ถูกดึงข้อมูลออกไป หากมีการดึงข้อมูลที่เก็บก่อนหน้านี้แล้ว Bazel จะดึงข้อมูลอีกครั้งก็ต่อเมื่อคำจำกัดความมีการเปลี่ยนแปลงเท่านั้น
คุณใช้คำสั่ง fetch
เพื่อเริ่มต้นการดึงข้อมูลล่วงหน้าสำหรับที่เก็บ เป้าหมาย หรือที่เก็บที่จำเป็นทั้งหมดเพื่อดำเนินการบิลด์ได้ ความสามารถนี้จะเปิดใช้บิลด์ออฟไลน์โดยใช้ตัวเลือก --nofetch
ตัวเลือก --fetch
มีไว้เพื่อจัดการการเข้าถึงเครือข่าย ค่าเริ่มต้นคือ "จริง"
แต่เมื่อตั้งค่าเป็น "เท็จ" (--nofetch
) คำสั่งจะใช้ทรัพยากร Dependency เวอร์ชันที่แคชไว้ทั้งหมด และหากไม่มี คำสั่งจะทำให้ใช้งานไม่ได้
ดูตัวเลือกการดึงข้อมูล สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมการดึงข้อมูล
เลย์เอาต์ไดเรกทอรี
หลังจากดึงข้อมูลแล้ว คุณจะดูที่เก็บได้ในไดเรกทอรีย่อย external
ในฐานเอาต์พุตภายใต้ชื่อ Canonical
คุณเรียกใช้คำสั่งต่อไปนี้เพื่อดูเนื้อหาของที่เก็บที่มีชื่อ 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 ซึ่งเป็นระบบย่อยของทรัพยากร Dependency ภายนอกแบบใหม่ไม่ทำงานกับคำจำกัดความของที่เก็บโดยตรง แต่จะสร้างกราฟทรัพยากร Dependency จากโมดูล เรียกใช้ส่วนขยายที่ด้านบนของกราฟ และกำหนด Repos ตามนั้น
โมดูลของ 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")
โมดูลจะต้องแสดงรายการทรัพยากร Dependency โดยตรงเท่านั้น ซึ่ง Bzlmod จะค้นหาในรีจิสทรีของ Bazel โดยค่าเริ่มต้นคือ Bazel Central Registry รีจิสทรีมีไฟล์ MODULE.bazel
ของการอ้างอิงซึ่งช่วยให้ Bazel ค้นพบกราฟทรัพยากร Dependency แบบสับเปลี่ยนทั้งหมดก่อนที่จะแปลงเวอร์ชันได้
หลังจากแก้ปัญหาเวอร์ชัน หากเลือกเวอร์ชันใดเวอร์ชันหนึ่งสำหรับแต่ละโมดูลแล้ว Bazel จะปรึกษากับรีจิสทรีอีกครั้งเพื่อดูวิธีกำหนดที่เก็บสำหรับแต่ละโมดูล
(ในกรณีส่วนใหญ่คือใช้ http_archive
)
โมดูลยังสามารถระบุข้อมูลที่กำหนดเองที่เรียกว่าแท็ก ซึ่งจะแสดงโดยส่วนขยายโมดูลหลังจากความละเอียดของโมดูลเพื่อกำหนดที่เก็บเพิ่มเติม ส่วนขยายเหล่านี้มีความสามารถคล้ายกับกฎที่เก็บ โดยทำให้สามารถดำเนินการต่างๆ เช่น I/O ไฟล์และการส่งคำขอเครือข่าย นอกเหนือจากวัตถุประสงค์อื่นๆ แล้ว Bazel ยังทำให้ Bazel โต้ตอบกับระบบจัดการแพ็กเกจอื่นๆ ขณะเดียวกันก็เคารพกราฟทรัพยากร Dependency ที่สร้างจากโมดูล Bazel ด้วย
ลิงก์ภายนอกบน Bzlmod
- ตัวอย่างการใช้ Bzlmod ใน bazelbuild/ตัวอย่าง
- การยกเครื่องการพึ่งพาภายนอกของ Bazel (เอกสารการออกแบบ Bzlmod ต้นฉบับ)
- การบรรยายในงาน BazelCon 2021 ใน Bzlmod
- การเสวนาเกี่ยวกับวันชุมชนชาว Bazel ใน Bzlmod
กำหนดที่เก็บด้วย WORKSPACE
ก่อนหน้านี้ คุณจัดการทรัพยากร Dependency ภายนอกได้โดยกำหนดที่เก็บในไฟล์ 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",
)
ข้อมูลโค้ดกำหนดที่เก็บซึ่งมีชื่อ Canonical คือ foo
ในระบบ WORKSPACE
โดยค่าเริ่มต้น ชื่อ Canonical ของที่เก็บจะเป็นชื่อที่เห็นได้ชัดของที่เก็บอื่นๆ ด้วย
ดูรายการทั้งหมดของฟังก์ชันที่มีในไฟล์ WORKSPACE
ข้อบกพร่องของระบบ WORKSPACE
ในช่วงหลายปีที่ผ่านมานับตั้งแต่เปิดตัวระบบ WORKSPACE
ผู้ใช้ได้รายงานประเด็นปัญหาต่างๆ มากมาย เช่น
- Bazel ไม่ได้ประเมินไฟล์
WORKSPACE
ของทรัพยากร Dependency ทั้งหมด ดังนั้นจึงต้องกำหนดทรัพยากร Dependency แบบสับเปลี่ยนทั้งหมดในไฟล์WORKSPACE
ของที่เก็บหลัก นอกเหนือจากการขึ้นต่อกันโดยตรง - ในการแก้ปัญหานี้ โปรเจ็กต์ได้ใช้รูปแบบ "deps.bzl" ซึ่งจะกำหนดมาโครซึ่งจะระบุที่เก็บหลายรายการและขอให้ผู้ใช้เรียกมาโครนี้ในไฟล์
WORKSPACE
- ซึ่งก็มีปัญหาของตัวเอง กล่าวคือ มาโครไม่สามารถ
load
ไฟล์.bzl
อื่นๆ ได้ โปรเจ็กต์เหล่านี้จึงต้องกำหนดทรัพยากร Dependency แบบทรานซิทีฟในมาโคร "deps" นี้ หรือเลี่ยงปัญหานี้โดยให้ผู้ใช้เรียกใช้มาโคร "deps" หลายชั้น - Bazel ประเมินไฟล์
WORKSPACE
ตามลำดับ นอกจากนี้ การระบุการขึ้นต่อกันโดยใช้http_archive
ด้วย URL โดยไม่มีข้อมูลเวอร์ชันใดๆ ซึ่งหมายความว่าจะไม่มีวิธีที่เชื่อถือได้ในการแปลงเวอร์ชันในกรณีที่เป็น Diamond Dependency (A
ขึ้นอยู่กับB
และC
ขณะที่ทั้งB
และC
ต่างก็ขึ้นอยู่กับD
เวอร์ชันที่แตกต่างกัน)
- ซึ่งก็มีปัญหาของตัวเอง กล่าวคือ มาโครไม่สามารถ
เนื่องจาก WORKSPACE ขาดแคลน Bzlmod จะมาแทนที่ระบบ WORKSPACE เดิมใน Bazel รุ่นต่อๆ ไป โปรดอ่านคำแนะนำในการย้ายข้อมูล Bzlmod เกี่ยวกับวิธีย้ายข้อมูลไปยัง Bzlmod