หน้าเว็บนี้ครอบคลุมข้อมูลพื้นฐานของการใช้มาโคร และรวมกรณีการใช้งานทั่วไป การแก้ไขข้อบกพร่อง และกฎเกณฑ์ต่างๆ
มาโครเป็นฟังก์ชันที่เรียกจากไฟล์ BUILD
ซึ่งสร้างอินสแตนซ์กฎได้
หลักๆ แล้วมาโครจะใช้สำหรับการสรุปและการนำกฎที่มีอยู่มาใช้ใหม่
และมาโครอื่นๆ ในช่วงท้ายของ
โหลด มาโครไม่มีอยู่อีกต่อไป
และ Bazel เห็นเฉพาะชุดกฎที่สร้างขึ้นมาอย่างเป็นรูปธรรมเท่านั้น
การใช้งาน
กรณีการใช้งานทั่วไปของมาโครคือเมื่อคุณต้องการใช้กฎซ้ำ
ตัวอย่างเช่น Genrule ในไฟล์ BUILD
จะสร้างไฟล์โดยใช้
//:generator
ที่มีฮาร์ดโค้ดอาร์กิวเมนต์ some_arg
ในคำสั่ง:
genrule(
name = "file",
outs = ["file.txt"],
cmd = "$(location //:generator) some_arg > $@",
tools = ["//:generator"],
)
หากต้องการสร้างไฟล์เพิ่มที่มีอาร์กิวเมนต์ต่างกัน คุณอาจต้อง
แยกโค้ดนี้ไปยังฟังก์ชันมาโคร เราจะเรียกมาโคร file_generator
ซึ่ง
มีพารามิเตอร์ name
และ arg
โดยแทนที่ Genrule ด้วยคำสั่งต่อไปนี้
load("//path:generator.bzl", "file_generator")
file_generator(
name = "file",
arg = "some_arg",
)
file_generator(
name = "file-two",
arg = "some_arg_two",
)
file_generator(
name = "file-three",
arg = "some_arg_three",
)
ตรงนี้คุณโหลดสัญลักษณ์ file_generator
จากไฟล์ .bzl
ซึ่งอยู่
ในแพ็กเกจ //path
โดยวางคำจำกัดความของฟังก์ชันมาโครไว้ใน
.bzl
โปรดดูแลไฟล์ BUILD
ให้สะอาดตาและประกาศชื่อ .bzl
สามารถโหลดไฟล์จากแพ็กเกจใดก็ได้ในพื้นที่ทำงาน
สุดท้าย ใน path/generator.bzl
ให้เขียนคำจำกัดความของมาโครเป็น
ห่อหุ้ม (Encapsulate) และกำหนดพารามิเตอร์ Genrule เดิม
def file_generator(name, arg, visibility=None):
native.genrule(
name = name,
outs = [name + ".txt"],
cmd = "$(location //:generator) %s > $@" % arg,
tools = ["//:generator"],
visibility = visibility,
)
คุณยังสามารถใช้มาโครเพื่อเชื่อมโยงกฎต่างๆ เข้าด้วยกัน ตัวอย่างนี้แสดงเชน genrules โดยที่ Genrule ใช้เอาต์พุตของ Genrule ก่อนหน้าเป็นอินพุต
def chained_genrules(name, visibility=None):
native.genrule(
name = name + "-one",
outs = [name + ".one"],
cmd = "$(location :tool-one) $@",
tools = [":tool-one"],
visibility = ["//visibility:private"],
)
native.genrule(
name = name + "-two",
srcs = [name + ".one"],
outs = [name + ".two"],
cmd = "$(location :tool-two) $< $@",
tools = [":tool-two"],
visibility = visibility,
)
ตัวอย่างนี้กำหนดค่าการเปิดเผยให้กับ Genrule ที่ 2 เท่านั้น วิธีนี้ช่วยให้ ผู้เขียนมาโครเพื่อซ่อนเอาต์พุตของกฎขั้นกลางไม่ให้ขึ้นอยู่กับ เป้าหมายอื่นๆ ในพื้นที่ทำงาน
มาโครการขยาย
เมื่อต้องการตรวจสอบสิ่งที่มาโครทำ ให้ใช้คำสั่ง query
กับ
--output=build
เพื่อดูแบบฟอร์มที่ขยาย
$ bazel query --output=build :file
# /absolute/path/test/ext.bzl:42:3
genrule(
name = "file",
tools = ["//:generator"],
outs = ["//test:file.txt"],
cmd = "$(location //:generator) some_arg > $@",
)
กำลังสร้างอินสแตนซ์กฎเนทีฟ
กฎเนทีฟ (กฎที่ไม่ต้องใช้คำสั่ง load()
) สามารถมีได้
สร้างอินสแตนซ์จากโมดูลเนทีฟ
def my_macro(name, visibility=None):
native.cc_library(
name = name,
srcs = ["main.cc"],
visibility = visibility,
)
หากต้องการทราบชื่อแพ็กเกจ (เช่น ไฟล์ BUILD
ใดเรียกใช้เมธอด
) ให้ใช้ฟังก์ชัน native.package_name()
โปรดทราบว่า native
ใช้ได้ใน .bzl
ไฟล์เท่านั้น ไม่ใช่ BUILD
ไฟล์
ความละเอียดของป้ายกำกับในมาโคร
เนื่องจากมาโครจะได้รับการประเมินในระยะการโหลด
ระบบจะแปลสตริงป้ายกำกับ เช่น "//foo:bar"
ที่เกิดขึ้นในมาโคร
เมื่อเทียบกับไฟล์ BUILD
ที่ใช้มาโครมากกว่าเมื่อเทียบกับ
ไฟล์ .bzl
ที่กำหนดไว้ ลักษณะการทำงานเช่นนี้โดยทั่วไปไม่เป็นที่ต้องการ
สำหรับมาโครที่มีไว้ใช้ในที่เก็บอื่นๆ เช่น
เป็นส่วนหนึ่งของชุดกฎ Starlark ที่เผยแพร่
หากต้องการให้มีลักษณะการทำงานเดียวกันกับกฎของ Starlark ให้รวมสตริงป้ายกำกับด้วยเมธอด
เครื่องมือสร้าง Label
:
# @my_ruleset//rules:defs.bzl
def my_cc_wrapper(name, deps = [], **kwargs):
native.cc_library(
name = name,
deps = deps + select({
# Due to the use of Label, this label is resolved within @my_ruleset,
# regardless of its site of use.
Label("//config:needs_foo"): [
# Due to the use of Label, this label will resolve to the correct target
# even if the canonical name of @dep_of_my_ruleset should be different
# in the main repo, such as due to repo mappings.
Label("@dep_of_my_ruleset//tools:foo"),
],
"//conditions:default": [],
}),
**kwargs,
)
การแก้ไขข้อบกพร่อง
bazel query --output=build //my/path:all
จะแสดงวิธีที่ไฟล์BUILD
หลังการประเมิน มาโคร โลก ลูป ทั้งหมดจะขยายออก รู้จัก ข้อจำกัด: ขณะนี้นิพจน์select
ยังไม่แสดงในเอาต์พุตคุณจะกรองเอาต์พุตโดยอิงตาม
generator_function
(ฟังก์ชันใด) สร้างกฎ) หรือgenerator_name
(แอตทริบิวต์ชื่อของมาโคร):bash $ bazel query --output=build 'attr(generator_function, my_macro, //my/path:all)'
หากต้องการดูว่ามีการสร้างกฎ
foo
ไว้ที่ใดในไฟล์BUILD
คุณจะต้อง ให้ลองทำตามเคล็ดลับต่อไปนี้ แทรกเส้นนี้ใกล้กับด้านบนของBUILD
ไฟล์:cc_library(name = "foo")
เรียกใช้ Bazel คุณจะได้รับข้อยกเว้นเมื่อ มีการสร้างกฎfoo
(เนื่องจากชื่อขัดแย้ง) ซึ่งจะแสดง สแต็กเทรซเต็มรูปแบบคุณยังใช้ print เพื่อแก้ไขข้อบกพร่องได้ด้วย จะแสดง ข้อความเป็นบรรทัด
DEBUG
ในบันทึกระหว่างกระบวนการโหลด ยกเว้นในกรณีพิเศษ ให้นำการเรียกใช้print
รายการออก หรือทําให้เป็นเงื่อนไขภายใต้ พารามิเตอร์debugging
ที่มีค่าเริ่มต้นเป็นFalse
ก่อนส่งรหัสไปยัง สถานีรถไฟ
ข้อผิดพลาด
หากต้องการส่งข้อผิดพลาด ให้ใช้ฟังก์ชันล้มเหลว
อธิบายให้ผู้ใช้ทราบอย่างชัดเจนถึงสิ่งที่ผิดพลาดและวิธีแก้ไขไฟล์ BUILD
ระบบไม่สามารถตรวจจับข้อผิดพลาดได้
def my_macro(name, deps, visibility=None):
if len(deps) < 2:
fail("Expected at least two values in deps")
# ...
การประชุม
ฟังก์ชันสาธารณะทั้งหมด (ฟังก์ชันที่ไม่ได้ขึ้นต้นด้วยขีดล่าง) ที่ กฎอินสแตนซ์ต้องมีอาร์กิวเมนต์
name
อาร์กิวเมนต์นี้ไม่ควรเป็น ไม่บังคับ (ไม่ต้องใส่ค่าเริ่มต้น)ฟังก์ชันสาธารณะควรใช้ docstring ต่อจาก Python การประชุมของ Google
ในไฟล์
BUILD
อาร์กิวเมนต์name
ของมาโครต้องเป็นคีย์เวิร์ด (ไม่ใช่อาร์กิวเมนต์ตำแหน่ง)แอตทริบิวต์
name
ของกฎที่มาโครสร้างขึ้นควรมีชื่อ เป็นคำนำหน้า ตัวอย่างเช่นmacro(name = "foo")
สามารถสร้างcc_library
foo
และกฎใหม่foo_gen
ในกรณีส่วนใหญ่ พารามิเตอร์ที่ไม่บังคับควรมีค่าเริ่มต้นเป็น
None
สามารถส่งNone
ไปยังกฎที่มีอยู่ได้โดยตรง ซึ่งจะปฏิบัติเช่นเดียวกับ คุณไม่ได้ส่งผ่านในอาร์กิวเมนต์ใดๆ ดังนั้น จึงไม่จำเป็นต้องเปลี่ยน กับ0
,False
หรือ[]
สำหรับวัตถุประสงค์นี้ มาโครควรเลื่อน กฎที่สร้างขึ้น เนื่องจากค่าเริ่มต้นอาจซับซ้อนหรือมีการเปลี่ยนแปลง นอกจากนี้ พารามิเตอร์ที่ตั้งไว้เป็นค่าเริ่มต้นอย่างชัดแจ้ง ดูแตกต่างจากวิดีโอที่ไม่ได้ตั้งค่า (หรือตั้งค่าเป็นNone
) เมื่อเข้าถึง ผ่านภาษาการค้นหาหรือระบบภายในของระบบบิลด์มาโครควรมีอาร์กิวเมนต์
visibility
ที่ไม่บังคับ