ส่วนขยายโมดูลช่วยให้ผู้ใช้ขยายระบบโมดูลได้โดยการอ่านข้อมูลอินพุตจากโมดูลต่างๆ ในกราฟทรัพยากร Dependency ดำเนินการตรรกะที่จำเป็นเพื่อแก้ไขทรัพยากร Dependency และสุดท้ายสร้างที่เก็บด้วยการเรียกใช้กฎที่เก็บ ส่วนขยายเหล่านี้มีความสามารถคล้ายกับกฎที่เก็บ ซึ่งช่วยให้ดำเนินการ I/O ไฟล์ ส่งคำขอเครือข่าย และอื่นๆ ได้ นอกเหนือจากวัตถุประสงค์อื่นๆ แล้ว Bazel ยังช่วยให้ Bazel โต้ตอบกับระบบจัดการแพ็กเกจอื่นๆ ขณะเดียวกันก็เคารพกราฟการขึ้นต่อกันที่สร้างขึ้นจากโมดูล 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
เพื่อนำ Repos ที่ส่วนขยายสร้างขึ้นไปไว้ในขอบเขตของโมดูลปัจจุบัน
use_repo(maven, "maven")
Repos ที่สร้างโดยส่วนขยายเป็นส่วนหนึ่งของ API ในตัวอย่างนี้ ส่วนขยายโมดูล "maven" สัญญาว่าจะสร้างที่เก็บชื่อ maven
จากประกาศข้างต้น ส่วนขยายจะแก้ไขป้ายกํากับได้อย่างเหมาะสม เช่น @maven//:org_junit_junit
ให้ชี้ไปยังที่เก็บที่สร้างโดยส่วนขยาย "maven"
คำจำกัดความของส่วนขยาย
คุณสามารถระบุส่วนขยายโมดูลได้ในลักษณะเดียวกับกฎที่เก็บ โดยใช้ฟังก์ชัน module_extension
อย่างไรก็ตาม แม้ว่ากฎที่เก็บจะมีแอตทริบิวต์จำนวนหนึ่ง แต่ส่วนขยายโมดูลจะมี tag_class
ซึ่งแต่ละรายการจะมีแอตทริบิวต์จำนวนหนึ่ง คลาสแท็กจะกำหนดสคีมาสำหรับแท็กที่ส่วนขยายนี้ใช้ ตัวอย่างเช่น ส่วนขยาย "maven" ด้านบนอาจกำหนดไว้ดังต่อไปนี้
# @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 ที่คุณควรใช้ เนื่องจากอาจเปลี่ยนแปลงได้ตลอดเวลา
นโยบายการตั้งชื่อนี้หมายความว่าส่วนขยายแต่ละรายการจะมี "เนมสเปซที่เก็บ" ของตัวเอง ส่วนขยาย 2 รายการที่แตกต่างกันจะกำหนดที่เก็บที่มีชื่อเดียวกันได้โดยไม่ต้องเสี่ยงการปะทะ นอกจากนี้ยังหมายความว่า repository_ctx.name
รายงานชื่อ Canonical ของที่เก็บ ซึ่งไม่เหมือนกับชื่อที่ระบุในการเรียกใช้กฎที่เก็บ
เมื่อพิจารณาที่เก็บที่สร้างโดยส่วนขยายโมดูลแล้ว มีกฎระดับการเข้าถึงที่เก็บหลายกฎดังนี้
- ที่เก็บโมดูล Bazel สามารถดูที่เก็บทั้งหมดที่แนะนำในไฟล์
MODULE.bazel
ผ่านbazel_dep
และuse_repo
ได้ - ที่เก็บที่สร้างโดยส่วนขยายโมดูลจะเห็นที่เก็บทั้งหมดปรากฏในโมดูลที่โฮสต์ส่วนขยาย บวกที่เก็บอื่นๆ ทั้งหมดที่สร้างโดยส่วนขยายโมดูลเดียวกัน (ใช้ชื่อที่ระบุในการเรียกใช้กฎที่เก็บเป็นชื่อที่ปรากฏ)
- ซึ่งอาจทำให้เกิดข้อขัดแย้ง หากที่เก็บโมดูลเห็นที่เก็บที่ใช้ชื่อ
foo
อย่างชัดเจน และส่วนขยายสร้างที่เก็บที่มีชื่อที่ระบุfoo
ที่เก็บทั้งหมดที่สร้างขึ้นโดยส่วนขยายนั้นfoo
จะหมายถึงที่เก็บเก่า
- ซึ่งอาจทำให้เกิดข้อขัดแย้ง หากที่เก็บโมดูลเห็นที่เก็บที่ใช้ชื่อ
แนวทางปฏิบัติแนะนำ
ส่วนนี้จะอธิบายแนวทางปฏิบัติแนะนำในการเขียนส่วนขยายเพื่อให้ใช้งาน บำรุงรักษา และปรับให้เข้ากับการเปลี่ยนแปลงเมื่อเวลาผ่านไปได้ง่าย
ใส่ส่วนขยายแต่ละรายการในไฟล์แยกต่างหาก
เมื่อส่วนขยายอยู่ในไฟล์ที่ต่างกัน ส่วนขยายหนึ่งจะอนุญาตให้ส่วนขยายหนึ่งโหลดที่เก็บที่สร้างขึ้นโดยส่วนขยายอื่นได้ แม้ว่าคุณจะไม่ได้ใช้ฟังก์ชันนี้ แต่คุณควรใส่ไฟล์เหล่านั้นไว้ในไฟล์แยกต่างหากในกรณีที่จำเป็นต้องใช้ในภายหลัง นั่นเป็นเพราะการระบุส่วนขยายนั้นอิงตามไฟล์ ดังนั้นการย้ายส่วนขยายไปยังไฟล์อื่นในภายหลังจะเปลี่ยน API สาธารณะของคุณ และเป็นการเปลี่ยนแปลงที่เข้ากันไม่ได้แบบย้อนหลังสำหรับผู้ใช้