ส่วนขยายโมดูลช่วยให้ผู้ใช้ขยายระบบโมดูลได้โดยการอ่านข้อมูลอินพุต จากโมดูลต่างๆ ในกราฟทรัพยากร Dependency ได้ดำเนินการตรรกะที่จำเป็นเพื่อแก้ไข ทรัพยากร Dependency และสุดท้ายคือการสร้างที่เก็บโดยการเรียกใช้กฎที่เก็บ ส่วนขยายเหล่านี้ มีความสามารถคล้ายกับกฎที่เก็บ ซึ่งช่วยให้ดำเนินการ I/O ไฟล์ได้ ส่งคำขอเครือข่าย และอื่นๆ สำหรับเรื่องอื่นๆ พวกเขาช่วยให้ Bazel โต้ตอบกับระบบจัดการแพ็กเกจอื่นๆ ควบคู่ไปกับการทำตาม กราฟทรัพยากร Dependency ที่สร้างจากโมดูล Bazel
คุณสามารถกำหนดส่วนขยายโมดูลในไฟล์ .bzl
ได้เช่นเดียวกับกฎที่เก็บ คือ
ไม่เรียกใช้โดยตรง แต่แต่ละโมดูลจะระบุข้อมูลที่เรียกว่าแท็ก
สำหรับส่วนขยายในการอ่าน Bazel เรียกใช้ความละเอียดของโมดูลก่อนประเมิน
ส่วนขยาย ส่วนขยายจะอ่านแท็กทั้งหมดที่เป็นของส่วนขยายนั้นทั้งหมด
กราฟการขึ้นต่อกัน
การใช้ส่วนขยาย
ส่วนขยายจะโฮสต์อยู่ในโมดูล Bazel ด้วยตนเอง หากต้องการใช้ส่วนขยายใน
ก่อนอื่นให้เพิ่ม bazel_dep
ลงในโมดูลที่โฮสต์ส่วนขยาย จากนั้น
เรียกใช้ฟังก์ชันในตัวของ use_extension
เพื่อนำมาใช้ในขอบเขต ลองดูตัวอย่างต่อไปนี้ - ตัวอย่างข้อมูลจาก
MODULE.bazel
ไฟล์เพื่อใช้ "maven" ที่กำหนดไว้ใน
rules_jvm_external
โมดูล:
bazel_dep(name = "rules_jvm_external", version = "4.5")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
วิธีนี้จะเชื่อมโยงค่าที่ use_extension
แสดงผลกับตัวแปร ซึ่งทำให้ฟังก์ชัน
ใช้จุด-ไวยากรณ์เพื่อระบุแท็กสำหรับส่วนขยาย แท็กต้องเป็นไปตาม
สคีมาที่กำหนดโดยคลาสแท็กที่เกี่ยวข้องซึ่งระบุไว้ในแท็ก
คำจำกัดความของส่วนขยาย เช่น การระบุ
แท็ก maven.install
และ maven.artifact
:
maven.install(artifacts = ["org.junit:junit:4.13.2"])
maven.artifact(group = "com.google.guava",
artifact = "guava",
version = "27.0-jre",
exclusions = ["com.google.j2objc:j2objc-annotations"])
ใช้คำสั่ง use_repo
เพื่อเรียกที่เก็บ
ที่สร้างขึ้นจากส่วนขยายลงในขอบเขตของโมดูลปัจจุบัน
use_repo(maven, "maven")
Repos ที่สร้างโดยส่วนขยายเป็นส่วนหนึ่งของ API ในตัวอย่างนี้
"ผู้เชี่ยวชาญ" ส่วนขยายโมดูลสัญญาว่าจะสร้างที่เก็บชื่อ maven
ด้วยฟังก์ชัน
ข้างต้น ส่วนขยายจะแก้ไขป้ายกำกับได้อย่างถูกต้อง เช่น
@maven//:org_junit_junit
เพื่อชี้ไปยังที่เก็บที่ "ผู้เชี่ยวชาญ" สร้างขึ้น
ส่วนขยาย
คำจำกัดความของส่วนขยาย
คุณสามารถกำหนดส่วนขยายโมดูลได้ในลักษณะเดียวกับกฎที่เก็บ โดยใช้
module_extension
อย่างไรก็ตาม
แม้ว่ากฎที่เก็บจะมีแอตทริบิวต์จำนวนหนึ่ง แต่ส่วนขยายโมดูลจะมี
tag_class
โดยที่แต่ละรายการมีจำนวน
คลาสแท็กจะกำหนดสคีมาสำหรับแท็กที่ส่วนขยายนี้ใช้ สำหรับ
เช่น "ผู้เชี่ยวชาญ" ส่วนขยายข้างต้นอาจกำหนดไว้ดังต่อไปนี้
# @rules_jvm_external//:extensions.bzl
_install = tag_class(attrs = {"artifacts": attr.string_list(), ...})
_artifact = tag_class(attrs = {"group": attr.string(), "artifact": attr.string(), ...})
maven = module_extension(
implementation = _maven_impl,
tag_classes = {"install": _install, "artifact": _artifact},
)
ประกาศเหล่านี้แสดงให้เห็นว่าแท็ก maven.install
และ maven.artifact
ทําได้
ที่ระบุโดยใช้สคีมาแอตทริบิวต์ที่ระบุ
ฟังก์ชันการใช้งานส่วนขยายโมดูลคล้ายกับที่เก็บ
เว้นแต่ว่าผู้ใช้จะได้รับออบเจ็กต์ module_ctx
ซึ่งจะให้สิทธิ์เข้าถึงโมดูลทั้งหมดโดยใช้ส่วนขยายและแท็กที่เกี่ยวข้องทั้งหมด
จากนั้นฟังก์ชันการใช้งานจะเรียกกฎที่เก็บเพื่อสร้างที่เก็บ
# @rules_jvm_external//:extensions.bzl
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file") # a repo rule
def _maven_impl(ctx):
# This is a fake implementation for demonstration purposes only
# collect artifacts from across the dependency graph
artifacts = []
for mod in ctx.modules:
for install in mod.tags.install:
artifacts += install.artifacts
artifacts += [_to_artifact(artifact) for artifact in mod.tags.artifact]
# call out to the coursier CLI tool to resolve dependencies
output = ctx.execute(["coursier", "resolve", artifacts])
repo_attrs = _process_coursier_output(output)
# call repo rules to generate repos
for attrs in repo_attrs:
http_file(**attrs)
_generate_hub_repo(name = "maven", repo_attrs)
ข้อมูลระบุตัวตนของส่วนขยาย
ระบบจะระบุส่วนขยายโมดูลโดยใช้ชื่อและไฟล์ .bzl
ที่ปรากฏ
ในการโทรถึง use_extension
ในตัวอย่างต่อไปนี้ ส่วนขยาย maven
ถูกระบุโดยไฟล์ .bzl
@rules_jvm_external//:extension.bzl
และ
ชื่อ maven
:
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
การส่งออกส่วนขยายอีกครั้งจากไฟล์ .bzl
อื่นจะสร้างข้อมูลประจำตัวใหม่
และหากมีการใช้ส่วนขยายทั้ง 2 เวอร์ชันในกราฟโมดูลทรานซิทีฟ
จากนั้นระบบจะประเมินแยกต่างหากและจะเห็นเฉพาะแท็กที่เชื่อมโยง
ด้วยข้อมูลประจำตัวนั้นๆ
ในฐานะผู้เขียนส่วนขยาย คุณควรตรวจสอบว่าผู้ใช้จะใช้
จากหนึ่งไฟล์ .bzl
เดียว
ชื่อและระดับการเข้าถึงที่เก็บ
Repos ที่สร้างโดยส่วนขยายมีชื่อ Canonical ในรูปแบบ module_repo_canonical_name~extension_name~repo_name
สำหรับส่วนขยายที่โฮสต์ใน
โมดูลราก module_repo_canonical_name
ส่วนคือ
แทนที่ด้วยสตริง _main
โปรดทราบว่ารูปแบบของชื่อ Canonical ไม่ใช่
API ที่คุณควรใช้ แต่อาจมีการเปลี่ยนแปลงได้ตลอดเวลา
นโยบายการตั้งชื่อนี้หมายความว่าส่วนขยายแต่ละรายการจะมี "เนมสเปซที่เก็บ" ของตนเอง สอง
ส่วนขยายที่แตกต่างกัน แต่ละส่วนขยายจะสามารถกำหนดที่เก็บที่มีชื่อเดียวกันได้โดยไม่ต้องเสี่ยง
การชน และยังหมายความว่า repository_ctx.name
รายงานชื่อ Canonical ด้วย
ของที่เก็บ ซึ่งไม่เหมือนกับชื่อที่ระบุในกฎที่เก็บ
การโทร
การพิจารณาที่เก็บที่สร้างโดยส่วนขยายโมดูลมีดังนี้ กฎการเปิดเผยที่เก็บหลายกฎ ได้แก่
- ที่เก็บโมดูล Bazel จะเห็นที่เก็บทั้งหมดที่แนะนำในไฟล์
MODULE.bazel
ผ่านbazel_dep
และuse_repo
- ที่เก็บที่สร้างโดยส่วนขยายโมดูลสามารถดูที่เก็บทั้งหมดที่แสดงต่อ
ที่โฮสต์ส่วนขยาย และที่เก็บอื่นๆ ทั้งหมดที่สร้างขึ้นโดย
ส่วนขยายโมดูลเดียวกัน (ใช้ชื่อที่ระบุในการเรียกใช้กฎที่เก็บเป็น
)
- ซึ่งอาจทำให้เกิดข้อขัดแย้ง หากที่เก็บโมดูลเห็นที่เก็บที่มี
ชื่อที่ปรากฏ
foo
และส่วนขยายจะสร้างที่เก็บที่มี ชื่อที่ระบุfoo
แล้วสำหรับที่เก็บทั้งหมดที่สร้างโดยส่วนขยายนั้นfoo
หมายถึงอันแรก
- ซึ่งอาจทำให้เกิดข้อขัดแย้ง หากที่เก็บโมดูลเห็นที่เก็บที่มี
ชื่อที่ปรากฏ
แนวทางปฏิบัติแนะนำ
ส่วนนี้จะอธิบายแนวทางปฏิบัติแนะนำในการเขียนส่วนขยายเพื่อให้ ใช้งานง่าย บำรุงรักษาได้ และปรับเปลี่ยนได้ดีตามการเปลี่ยนแปลงเมื่อเวลาผ่านไป
ใส่ส่วนขยายแต่ละรายการในไฟล์แยกต่างหาก
เมื่อส่วนขยายอยู่ในไฟล์ที่ต่างกัน ส่วนขยายหนึ่งจะทำให้ส่วนขยายหนึ่งโหลดได้ ที่เก็บที่สร้างโดยส่วนขยายอื่น แม้ว่าคุณจะไม่ได้ใช้สิ่งนี้ คุณควรแยกไฟล์เหล่านั้นไว้ในไฟล์แยกกัน เผื่อกรณีที่ต้องการ ในภายหลัง เพราะการระบุส่วนขยายนั้นพิจารณาจากไฟล์ ดังนั้นการย้าย ส่วนขยายลงในไฟล์อื่นในภายหลังจะเปลี่ยน API สาธารณะของคุณและเป็นการย้อนกลับ การเปลี่ยนแปลงที่เข้ากันไม่ได้กับผู้ใช้
ระบุระบบปฏิบัติการและสถาปัตยกรรม
หากส่วนขยายต้องใช้ระบบปฏิบัติการหรือประเภทสถาปัตยกรรม
อย่าลืมระบุข้อมูลนี้ในคำจำกัดความส่วนขยายโดยใช้ os_dependent
และแอตทริบิวต์บูลีน arch_dependent
รายการ ซึ่งทำให้ Bazel ทราบว่า
ต้องได้รับการประเมินซ้ำหากมีการเปลี่ยนแปลงอย่างใดอย่างหนึ่ง
เฉพาะโมดูลรูทเท่านั้นที่จะมีผลต่อชื่อที่เก็บโดยตรง
โปรดทราบว่าเมื่อส่วนขยายสร้างที่เก็บ จะมีการสร้างที่เก็บขึ้นภายใน
Namespace ของส่วนขยาย ซึ่งหมายความว่าการชนอาจเกิดขึ้นหากไม่เหมือนกัน
โมดูลจะใช้ส่วนขยายเดียวกัน และจบลงด้วยการสร้างที่เก็บที่มี
ชื่อ ซึ่งมักจะแสดงเป็น tag_class
ของส่วนขยายโมดูลที่มี name
ที่ส่งผ่านเป็นค่า name
ของกฎที่เก็บ
ตัวอย่างเช่น สมมติว่าโมดูลราก A
ขึ้นอยู่กับโมดูล B
ทั้ง 2 โมดูล
ขึ้นอยู่กับโมดูล mylang
หากโทรทั้ง A
และ B
mylang.toolchain(name="foo")
ทั้งคู่จะพยายามสร้างที่เก็บชื่อ
foo
ภายในโมดูล mylang
และมีข้อผิดพลาดเกิดขึ้น
คุณหลีกเลี่ยงปัญหานี้ได้ด้วยการนำความสามารถในการตั้งชื่อที่เก็บโดยตรงออก หรืออนุญาตเฉพาะโมดูลรูทเท่านั้น คุณสามารถอนุญาตโมดูลรูท ความสามารถเพราะ ไม่มีอะไร ขึ้นอยู่กับความสามารถนั้น คุณจึงไม่ต้องกังวลเกี่ยวกับ โมดูลอื่นที่สร้างชื่อที่ขัดแย้งกัน