อย่าลืมนัดของเรา: BazelCon 2023 จะจัดขึ้นในวันที่ 24-25 ตุลาคมที่ Google ที่มิวนิก ดูข้อมูลเพิ่มเติม

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

รายงานปัญหา ดูแหล่งที่มา

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

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

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

แนวคิด

ที่เก็บ

ไดเรกทอรีที่มีไฟล์ WORKSPACE หรือ WORKSPACE.bazel ที่มีไฟล์ต้นฉบับที่จะใช้ในบิวด์ Bazel มักจะย่อให้สั้นลงเหลือเพียง repo

ที่เก็บหลัก

ที่เก็บที่ใช้คําสั่ง Bazel ปัจจุบันอยู่

Workspace

สภาพแวดล้อมที่คําสั่ง Bazel ทั้งหมดแชร์ไว้ในที่เก็บหลักเดียวกัน

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

ชื่อที่เก็บมาตรฐาน

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

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

ชื่อที่เก็บที่เห็นได้ชัด

ชื่อที่เก็บจะระบุได้โดยบริบทของที่เก็บอื่น ซึ่งอาจถือว่าเป็น "ชื่อเล่น" ของที่เก็บ: ที่เก็บซึ่งมีชื่อ Canonical 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 จะดึงข้อมูลอีกครั้งก็ต่อเมื่อมีการเปลี่ยนแปลง

การจัดวางไดเรกทอรี

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

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

ls $(bazel info output_base)/external/ canonical_name 

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

Bzlmod ซึ่งเป็นระบบย่อยที่ใช้ทรัพยากรภายนอกระบบใหม่นี้ไม่สามารถทํางานกับที่เก็บได้โดยตรง แต่จะสร้างกราฟ Dependency จากโมดูลแทน โดยเรียกใช้ extensions ที่ด้านบนของกราฟ และกําหนดการแสดงผลตามนั้น

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 ค้นพบกราฟการพึ่งพาการเปลี่ยนรูปแบบทั้งหมดได้ก่อนที่จะดําเนินการแปลงเวอร์ชัน

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

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

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