กฎที่เก็บ

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

หน้านี้จะพูดถึงวิธีสร้างกฎของที่เก็บและแสดงตัวอย่างสำหรับรายละเอียดเพิ่มเติม

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

การสร้างกฎของที่เก็บ

ในไฟล์ .bzl ให้ใช้ฟังก์ชัน repository_rule เพื่อสร้างกฎที่เก็บใหม่และเก็บไว้ในตัวแปรร่วม

คุณใช้กฎที่เก็บที่กำหนดเองได้เช่นเดียวกับกฎที่เก็บเนทีฟ โดยมีแอตทริบิวต์ name ที่จำเป็นและเป้าหมายทุกรายการที่มีอยู่ในไฟล์บิลด์อาจเรียกว่า @<name>//package:target โดยที่ <name> คือค่าของแอตทริบิวต์ name

ระบบจะโหลดกฎเมื่อคุณสร้างกฎขึ้นอย่างชัดแจ้ง หรือหากกฎนั้นเป็นทรัพยากร Dependency ของบิลด์ ในกรณีนี้ Bazel จะเรียกใช้ฟังก์ชัน implementation ฟังก์ชันนี้อธิบายวิธีสร้างที่เก็บ เนื้อหา และไฟล์ BUILD

Attributes

แอตทริบิวต์คืออาร์กิวเมนต์ของกฎที่ส่งผ่านเป็นคำสั่งไปยังอาร์กิวเมนต์ของกฎ attrs ระบบจะกำหนดแอตทริบิวต์และประเภทของแอตทริบิวต์เมื่อคุณกำหนดกฎที่เก็บ ตัวอย่างการกำหนดแอตทริบิวต์ url และ sha256 เป็นสตริงมีดังนี้

local_repository = repository_rule(
    implementation=_impl,
    local=True,
    attrs={
        "url": attr.string(mandatory=True)
        "sha256": attr.string(mandatory=True)
    }
)

หากต้องการเข้าถึงแอตทริบิวต์ภายในฟังก์ชันการใช้งาน ให้ใช้ repository_ctx.attr.<attribute_name> ดังนี้

def _impl(repository_ctx):
    url = repository_ctx.attr.url
    checksum = repository_ctx.attr.sha256

repository_rule ทั้งหมดมีแอตทริบิวต์ที่กำหนดไว้โดยปริยาย (เช่นเดียวกับกฎของบิลด์) แอตทริบิวต์โดยนัย 2 รายการคือ name (เช่นเดียวกับกฎการสร้าง) และ repo_mapping คุณเข้าถึงชื่อของกฎที่เก็บได้ด้วย repository_ctx.name ความหมายของ repo_mapping จะเหมือนกับสำหรับกฎที่เก็บเนทีฟ local_repository และ new_local_repository

หากชื่อแอตทริบิวต์ขึ้นต้นด้วย _ จะเป็นแบบส่วนตัวและผู้ใช้ตั้งค่าไม่ได้

ฟังก์ชันการใช้งาน

กฎที่เก็บทั้งหมดต้องมีฟังก์ชัน implementation ซึ่งประกอบด้วยตรรกะจริงของกฎ และจะดำเนินการในขั้นตอนการโหลดอย่างเคร่งครัด

ฟังก์ชันดังกล่าวมีพารามิเตอร์อินพุต repository_ctx เพียงพารามิเตอร์เดียวเท่านั้น ฟังก์ชันจะแสดงผล None เพื่อแสดงว่ากฎนั้นทำซ้ำได้เมื่อมีพารามิเตอร์ที่ระบุ หรือดิกส์ที่มีชุดพารามิเตอร์สำหรับกฎนั้นซึ่งจะเปลี่ยนกฎนั้นให้กลายเป็นกฎที่ทำซ้ำได้ซึ่งสร้างที่เก็บเดียวกัน เช่น สำหรับกฎที่ติดตามที่เก็บ Git ที่จะส่งคืนตัวระบุคอมมิตที่เจาะจงแทน Branch แบบลอยซึ่งระบุไว้แต่แรก

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

def _impl(repository_ctx):
  repository_ctx.symlink(repository_ctx.attr.path, "")

local_repository = repository_rule(
    implementation=_impl,
    ...)

ฟังก์ชันการติดตั้งใช้งานจะทำงานเมื่อใด

ฟังก์ชันการใช้งานของที่เก็บจะทำงานเมื่อ Bazel ต้องการเป้าหมายจากที่เก็บนั้น เช่น เมื่อเป้าหมายอื่น (ในที่เก็บอื่น) ขึ้นอยู่กับเป้าหมายดังกล่าวหรือมีการกล่าวถึงในบรรทัดคำสั่ง จากนั้นฟังก์ชันการใช้งานก็จะสร้างที่เก็บในระบบไฟล์ ซึ่งเรียกว่า "การดึงข้อมูล" ที่เก็บ

ที่เก็บอาจไม่ถูกดึงข้อมูลอีกครั้งเมื่อมีบางอย่างเปลี่ยนแปลงที่จะทำให้ที่เก็บแตกต่างกัน ซึ่งแตกต่างจากเป้าหมายปกติ เนื่องจากมีบางสิ่งที่ Bazel ไม่สามารถตรวจจับการเปลี่ยนแปลงได้ หรือทำให้เกิดค่าใช้จ่ายมากเกินไปในทุกบิลด์ (เช่น สิ่งที่ดึงข้อมูลจากเครือข่าย) ดังนั้น ระบบจะดึงข้อมูลที่เก็บอีกครั้งเมื่อมีการเปลี่ยนแปลงข้อใดข้อหนึ่งต่อไปนี้

  • พารามิเตอร์ที่ส่งผ่านไปยังการประกาศของที่เก็บในไฟล์ WORKSPACE
  • โค้ด Starlark ประกอบด้วยการใช้งานที่เก็บ
  • ค่าของตัวแปรสภาพแวดล้อมใดๆ ที่ส่งไปยังเมธอด getenv() ของ repository_ctx หรือประกาศด้วยแอตทริบิวต์ environ ของ repository_rule ค่าของตัวแปรสภาพแวดล้อมเหล่านี้สามารถเดินสายในบรรทัดคำสั่งที่มีแฟล็ก --repo_env ได้
  • เนื้อหาของไฟล์ที่ส่งไปยัง read(), execute() และวิธีการที่คล้ายกันของ repository_ctx ซึ่งอ้างถึงโดยป้ายกำกับ (เช่น //mypkg:label.txt แต่ไม่ใช่ mypkg/label.txt)
  • เมื่อมีการเรียกใช้ bazel sync

มีพารามิเตอร์ 2 ตัวของ repository_rule ที่ควบคุมเวลาในการดึงข้อมูลที่เก็บอีกครั้ง ดังนี้

  • หากตั้งค่าแฟล็ก configure ไว้ ระบบจะดึงข้อมูลที่เก็บอีกครั้งใน bazel sync ก็ต่อเมื่อมีการส่งพารามิเตอร์ --configure ไปยังที่เก็บ (หากไม่ได้ตั้งค่าแอตทริบิวต์ คำสั่งนี้จะไม่ทำให้เกิดการดึงข้อมูลอีกครั้ง)
  • หากมีการตั้งค่าแฟล็ก local นอกเหนือจากกรณีข้างต้นแล้ว ระบบจะดึงข้อมูลที่เก็บอีกครั้งเมื่อเซิร์ฟเวอร์ Bazel รีสตาร์ทหรือเมื่อไฟล์ที่มีผลต่อการประกาศของที่เก็บมีการเปลี่ยนแปลง (เช่น ไฟล์ WORKSPACE หรือไฟล์ที่โหลด) ไม่ว่าการเปลี่ยนแปลงดังกล่าวจะส่งผลให้เกิดการเปลี่ยนแปลงการประกาศที่เก็บหรือโค้ดของที่เก็บหรือไม่ก็ตาม

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

การรีสตาร์ทฟังก์ชันการใช้งาน

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

การบังคับให้ดึงข้อมูลที่เก็บภายนอกอีกครั้ง

บางครั้งที่เก็บภายนอกอาจล้าสมัยโดยไม่มีการเปลี่ยนแปลงใดๆ กับคำจำกัดความหรือทรัพยากร Dependency เช่น แหล่งที่มาการดึงข้อมูลที่เก็บอาจติดตามสาขาใดสาขาหนึ่งของที่เก็บของบุคคลที่สาม และคอมมิตใหม่จะใช้ในสาขานั้น ในกรณีนี้ คุณขอให้ Bazel ดึงข้อมูลที่เก็บภายนอกทั้งหมดอีกครั้งโดยไม่มีเงื่อนไขได้โดยเรียกใช้ bazel sync

นอกจากนี้ กฎบางอย่างจะตรวจสอบเครื่องภายในระบบและอาจล้าสมัยหากมีการอัปเกรดเครื่องภายใน ในส่วนนี้ คุณจะขอให้ Bazel ดึงข้อมูลอีกครั้งได้เฉพาะที่เก็บภายนอกที่คำจำกัดความ repository_rule กำหนดแอตทริบิวต์ configure ไว้เท่านั้น ให้ใช้ bazel sync --configure

ตัวอย่าง

  • เครื่องมือเชน C++ ที่กำหนดค่าอัตโนมัติ: ใช้กฎที่เก็บเพื่อสร้างไฟล์การกำหนดค่า C++ สำหรับ Bazel โดยอัตโนมัติโดยมองหาคอมไพเลอร์ C++ ในเครื่อง สภาพแวดล้อม และแฟล็กที่คอมไพเลอร์ C++ รองรับ

  • Goที่เก็บ ใช้ repository_rule หลายรายการในการกำหนดรายการทรัพยากร Dependency ที่จำเป็นต้องใช้กฎ Go

  • rules_jvm_external จะสร้างที่เก็บภายนอกที่เรียกว่า @maven โดยค่าเริ่มต้น ซึ่งจะสร้างเป้าหมายบิลด์สำหรับอาร์ติแฟกต์ Maven ทั้งหมดในโครงสร้างทรัพยากร Dependency ทางอ้อม