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

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

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

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

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

แนวคิด

ที่เก็บ

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

ที่เก็บหลัก

พื้นที่เก็บข้อมูลที่กําลังเรียกใช้คําสั่ง Bazel อยู่

Workspace

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

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

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

ชื่อ 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 จะดึงข้อมูลอีกครั้งก็ต่อเมื่อคำจำกัดความของรีโปมีการเปลี่ยนแปลงเท่านั้น

เลย์เอาต์ไดเรกทอรี

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

คุณสามารถเรียกใช้คําสั่งต่อไปนี้เพื่อดูเนื้อหาของรีโปที่มีชื่อตามหลักเกณฑ์ canonical_name

ls $(bazel info output_base)/external/ canonical_name 

จัดการทรัพยากร 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 ด้วย

กำหนดที่เก็บด้วย 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",
)

ข้อมูลโค้ดกำหนดที่เก็บซึ่งมีชื่อ Canonical คือ foo ในWORKSPACEระบบ โดยค่าเริ่มต้น ชื่อ Canonical ของรีโปจะเป็นชื่อที่ปรากฏต่อรีโปอื่นๆ ทั้งหมดด้วย

ข้อบกพร่องของระบบ WORKSPACE

ในช่วงหลายปีที่ผ่านมานับตั้งแต่เปิดตัวระบบ WORKSPACE ผู้ใช้ได้รายงานปัญหาที่พบมากมาย ซึ่งรวมถึงปัญหาต่อไปนี้

  • Bazel ไม่ได้ประเมินไฟล์ WORKSPACE ของทรัพยากร Dependency ทั้งหมด ดังนั้นต้องกำหนดทรัพยากร Dependency แบบสับเปลี่ยนทั้งหมดในไฟล์ 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