หน้านี้ครอบคลุมพื้นฐานของการใช้มาโคร รวมถึงกรณีการใช้งานทั่วไป การแก้ไขข้อบกพร่อง และการตั้งค่า
มาโครคือฟังก์ชันที่เรียกจากไฟล์ BUILD
ซึ่งสามารถสร้างอินสแตนซ์ของกฎได้
โดยส่วนใหญ่แล้ว มาโครจะใช้สำหรับการห่อหุ้มและการนำโค้ดของกฎที่มีอยู่และมาโครอื่นๆ กลับมาใช้ซ้ำ
มาโครมี 2 รูปแบบ ได้แก่ มาโครสัญลักษณ์ ซึ่งอธิบายไว้ในหน้านี้ และมาโครเดิม เราขอแนะนำให้ใช้มาโครเชิงสัญลักษณ์เพื่อความชัดเจนของโค้ดหากเป็นไปได้
มาโครเชิงสัญลักษณ์มีอาร์กิวเมนต์ที่พิมพ์ (การแปลงสตริงเป็นป้ายกำกับที่สัมพันธ์กับ
ตำแหน่งที่เรียกใช้มาโคร) และความสามารถในการจำกัดและระบุ
ระดับการมองเห็นของเป้าหมายที่สร้างขึ้น โดยได้รับการออกแบบมาให้รองรับการประเมินแบบเลื่อนเวลา (ซึ่งจะเพิ่มในการเปิดตัว Bazel ในอนาคต) มาโครสัญลักษณ์จะพร้อมใช้งานโดยค่าเริ่มต้นใน Bazel 8 เมื่อเอกสารนี้กล่าวถึง macros
จะหมายถึงมาโครสัญลักษณ์
ดูตัวอย่างที่เรียกใช้งานได้ของมาโครสัญลักษณ์ได้ในที่เก็บตัวอย่าง
การใช้งาน
มาโครกำหนดไว้ในไฟล์ .bzl
โดยการเรียกฟังก์ชัน macro()
ด้วยพารามิเตอร์ที่จำเป็น 2 รายการ ได้แก่ attrs
และ implementation
Attributes
attrs
รับพจนานุกรมของชื่อแอตทริบิวต์ไปยังประเภท
แอตทริบิวต์ ซึ่งแสดง
อาร์กิวเมนต์ของมาโคร แอตทริบิวต์ทั่วไป 2 รายการ ได้แก่ name
และ visibility
จะเพิ่มลงในมาโครทั้งหมดโดยปริยาย และจะไม่รวมอยู่ในพจนานุกรมที่ส่งไปยัง attrs
# macro/macro.bzl
my_macro = macro(
attrs = {
"deps": attr.label_list(mandatory = True, doc = "The dependencies passed to the inner cc_binary and cc_test targets"),
"create_test": attr.bool(default = False, configurable = False, doc = "If true, creates a test target"),
},
implementation = _my_macro_impl,
)
การประกาศประเภทแอตทริบิวต์ยอมรับ
พารามิเตอร์
mandatory
, default
และ doc
แอตทริบิวต์ส่วนใหญ่ยังยอมรับพารามิเตอร์
configurable
ซึ่งกำหนดว่าแอตทริบิวต์ยอมรับ
select
หรือไม่ หากแอตทริบิวต์เป็น configurable
ระบบจะแยกวิเคราะห์ค่าที่ไม่ใช่ select
เป็น select
ที่กำหนดค่าไม่ได้ - "foo"
จะกลายเป็น
select({"//conditions:default": "foo"})
ดูข้อมูลเพิ่มเติมในเลือก
การรับค่าแอตทริบิวต์ต่อ
มาโครมักมีไว้เพื่อครอบคลุมกฎ (หรือมาโครอื่น) และผู้เขียนมาโครมักต้องการส่งต่อแอตทริบิวต์ส่วนใหญ่ของสัญลักษณ์ที่ครอบคลุมโดยไม่มีการเปลี่ยนแปลง โดยใช้ **kwargs
ไปยังเป้าหมายหลักของมาโคร (หรือมาโครภายในหลัก)
มาโครสามารถรับค่าแอตทริบิวต์จากกฎหรือมาโครอื่นได้โดยการส่งกฎหรือสัญลักษณ์มาโครไปยังอาร์กิวเมนต์ inherit_attrs
ของ macro()
(คุณยังใช้สตริงพิเศษ "common"
แทนสัญลักษณ์กฎหรือมาโครเพื่อรับค่าแอตทริบิวต์ทั่วไปที่กำหนดสำหรับ
กฎการสร้างทั้งหมดของ Starlark ได้ด้วย)
เฉพาะแอตทริบิวต์สาธารณะเท่านั้นที่จะได้รับการสืบทอด และแอตทริบิวต์ในพจนานุกรมของมาโครเอง
attrs
จะลบล้างแอตทริบิวต์ที่สืบทอดมาซึ่งมีชื่อเดียวกัน คุณยังนำแอตทริบิวต์ที่รับช่วงมาออกได้โดยใช้ None
เป็นค่าในattrs
พจนานุกรม
# macro/macro.bzl
my_macro = macro(
inherit_attrs = native.cc_library,
attrs = {
# override native.cc_library's `local_defines` attribute
"local_defines": attr.string_list(default = ["FOO"]),
# do not inherit native.cc_library's `defines` attribute
"defines": None,
},
...
)
ค่าเริ่มต้นของแอตทริบิวต์ที่รับค่ามาซึ่งไม่บังคับจะถูกลบล้างเป็น None
เสมอ ไม่ว่าค่าเริ่มต้นของคำจำกัดความแอตทริบิวต์เดิมจะเป็นอะไรก็ตาม หากต้องการตรวจสอบหรือแก้ไขแอตทริบิวต์ที่ไม่บังคับที่รับค่ามา เช่น หากต้องการเพิ่มแท็กลงในแอตทริบิวต์ tags
ที่รับค่ามา คุณต้องตรวจสอบว่าได้จัดการกรณี None
ในฟังก์ชันการติดตั้งใช้งานของมาโครแล้ว
# macro/macro.bzl
def _my_macro_impl(name, visibility, tags, **kwargs):
# Append a tag; tags attr is an inherited non-mandatory attribute, and
# therefore is None unless explicitly set by the caller of our macro.
my_tags = (tags or []) + ["another_tag"]
native.cc_library(
...
tags = my_tags,
**kwargs,
)
...
การใช้งาน
implementation
รับฟังก์ชันที่มีตรรกะของมาโคร
ฟังก์ชันการใช้งานมักจะสร้างเป้าหมายโดยการเรียกกฎอย่างน้อย 1 รายการ และ
มักจะเป็นแบบส่วนตัว (ตั้งชื่อโดยมีขีดล่างนำหน้า) โดยทั่วไปแล้ว
จะตั้งชื่อเหมือนกับมาโคร แต่มีคำนำหน้าเป็น _
และคำต่อท้ายเป็น
_impl
ฟังก์ชันการติดตั้งใช้งานมาโครจะยอมรับพารามิเตอร์สำหรับอาร์กิวเมนต์แต่ละรายการ ซึ่งต่างจากฟังก์ชันการติดตั้งใช้งานกฎที่รับอาร์กิวเมนต์เดียว (ctx
) ซึ่งมีข้อมูลอ้างอิงถึงแอตทริบิวต์
# macro/macro.bzl
def _my_macro_impl(name, visibility, deps, create_test):
cc_library(
name = name + "_cc_lib",
deps = deps,
)
if create_test:
cc_test(
name = name + "_test",
srcs = ["my_test.cc"],
deps = deps,
)
หากมาโครรับช่วงแอตทริบิวต์ ฟังก์ชันการติดตั้งใช้งานต้องมี
**kwargs
พารามิเตอร์คีย์เวิร์ดที่เหลือ ซึ่งสามารถส่งต่อให้การเรียกที่
เรียกใช้กฎหรือมาโครย่อยที่รับช่วง (วิธีนี้จะช่วยให้มั่นใจได้ว่ามาโครจะไม่
เสียหากกฎหรือมาโครที่คุณรับค่ามาเพิ่มแอตทริบิวต์ใหม่
)
คำประกาศ
มาโครจะประกาศโดยการโหลดและเรียกคำจำกัดความในไฟล์ BUILD
# pkg/BUILD
my_macro(
name = "macro_instance",
deps = ["src.cc"] + select(
{
"//config_setting:special": ["special_source.cc"],
"//conditions:default": [],
},
),
create_tests = True,
)
ซึ่งจะสร้างเป้าหมาย
//pkg:macro_instance_cc_lib
และ//pkg:macro_instance_test
เช่นเดียวกับการเรียกกฎ หากตั้งค่าแอตทริบิวต์ในมาโครเป็น None
,
ระบบจะถือว่าแอตทริบิวต์นั้นถูกละเว้นโดยผู้เรียกของมาโคร ตัวอย่างเช่น การเรียกมาโคร 2 รายการต่อไปนี้มีความหมายเหมือนกัน
# pkg/BUILD
my_macro(name = "abc", srcs = ["src.cc"], deps = None)
my_macro(name = "abc", srcs = ["src.cc"])
โดยทั่วไปแล้วการดำเนินการนี้ไม่มีประโยชน์ในไฟล์ BUILD
แต่จะมีประโยชน์เมื่อ
ห่อมาโครภายในมาโครอื่นโดยใช้โปรแกรม
รายละเอียด
รูปแบบการตั้งชื่อสำหรับเป้าหมายที่สร้างขึ้น
ชื่อของเป้าหมายหรือมาโครย่อยที่สร้างโดยมาโครสัญลักษณ์ต้องตรงกับพารามิเตอร์ name
ของมาโคร หรือต้องมีคำนำหน้าเป็น name
ตามด้วย _
(แนะนำ) .
หรือ -
เช่น my_macro(name = "foo")
อาจสร้างได้เฉพาะไฟล์หรือเป้าหมายที่ชื่อ foo
หรือมีคำนำหน้าเป็น foo_
, foo-
หรือ foo.
เช่น foo_bar
เป้าหมายหรือไฟล์ที่ละเมิดรูปแบบการตั้งชื่อมาโครสามารถประกาศได้ แต่ จะสร้างไม่ได้และใช้เป็นทรัพยากร Dependency ไม่ได้
ไฟล์และเป้าหมายที่ไม่ใช่มาโครภายในแพ็กเกจเดียวกันกับอินสแตนซ์มาโครไม่ควรมีชื่อที่ขัดแย้งกับชื่อเป้าหมายมาโครที่อาจเกิดขึ้น แม้ว่าจะไม่มีการบังคับใช้การแยกเฉพาะนี้ก็ตาม เรากำลังดำเนินการใช้การประเมินแบบเลื่อนเวลาเพื่อปรับปรุงประสิทธิภาพของมาโครสัญลักษณ์ ซึ่งจะลดประสิทธิภาพในแพ็กเกจที่ละเมิดรูปแบบการตั้งชื่อ
ข้อจำกัด
มาโครสัญลักษณ์มีข้อจำกัดเพิ่มเติมบางอย่างเมื่อเทียบกับมาโครเดิม
มาโครเชิงสัญลักษณ์
- ต้องใช้อาร์กิวเมนต์
name
และอาร์กิวเมนต์visibility
- ต้องมีฟังก์ชัน
implementation
- อาจไม่แสดงค่า
- อาจไม่เปลี่ยนแปลงอาร์กิวเมนต์
- ต้องไม่เรียกใช้
native.existing_rules()
เว้นแต่จะเป็นมาโครพิเศษfinalizer
- อาจโทรหา
native.package()
ไม่ได้ - อาจโทรหา
glob()
ไม่ได้ - อาจโทรหา
native.environment_group()
ไม่ได้ - ต้องสร้างเป้าหมายที่มีชื่อตามรูปแบบการตั้งชื่อ
- อ้างอิงไฟล์อินพุตที่ไม่ได้ประกาศหรือส่งผ่านเป็นอาร์กิวเมนต์ไม่ได้
- อ้างอิงถึงเป้าหมายส่วนตัวของผู้โทรไม่ได้ (ดูรายละเอียดเพิ่มเติมได้ที่ระดับการมองเห็นและมาโคร)
ระดับการเข้าถึงและมาโคร
ระบบการมองเห็นช่วยปกป้องรายละเอียดการติดตั้งใช้งาน ทั้งมาโคร (สัญลักษณ์) และผู้เรียกใช้
โดยค่าเริ่มต้น เป้าหมายที่สร้างในมาโครสัญลักษณ์จะมองเห็นได้ภายในมาโคร
เอง แต่ไม่จำเป็นต้องมองเห็นได้สำหรับผู้เรียกมาโคร มาโครสามารถ "ส่งออก" เป้าหมายเป็น API สาธารณะได้โดยการส่งต่อค่าของแอตทริบิวต์ของตัวเอง visibility
ดังเช่นใน some_rule(..., visibility = visibility)
แนวคิดหลักของระดับการมองเห็นแบบแมโครมีดังนี้
ระบบจะตรวจสอบระดับการมองเห็นตามมาโครที่ประกาศเป้าหมาย ไม่ใช่แพ็กเกจที่เรียกใช้มาโคร
- กล่าวคือ การอยู่ในแพ็กเกจเดียวกันไม่ได้ทำให้เป้าหมายหนึ่งมองเห็นอีกเป้าหมายหนึ่งได้โดยอัตโนมัติ ซึ่งจะช่วยป้องกันไม่ให้เป้าหมายภายในของมาโคร กลายเป็นทรัพยากร Dependency ของมาโครอื่นๆ หรือเป้าหมายระดับบนสุดใน แพ็กเกจ
visibility
แอตทริบิวต์ทั้งหมดทั้งในกฎและมาโครจะรวมสถานที่ที่เรียกใช้กฎหรือมาโครโดยอัตโนมัติ- ดังนั้น เป้าหมายจะมองเห็นเป้าหมายอื่นๆ ที่ประกาศในมาโครเดียวกัน (หรือไฟล์
BUILD
หากไม่ได้อยู่ในมาโคร) โดยไม่มีเงื่อนไข
- ดังนั้น เป้าหมายจะมองเห็นเป้าหมายอื่นๆ ที่ประกาศในมาโครเดียวกัน (หรือไฟล์
ในทางปฏิบัติ หมายความว่าเมื่อมาโครประกาศเป้าหมายโดยไม่ได้ตั้งค่า visibility
เป้าหมายจะกลายเป็นเป้าหมายภายในมาโครโดยค่าเริ่มต้น (ระดับการเข้าถึงเริ่มต้นของแพ็กเกจจะไม่มีผลภายในมาโคร) การส่งออกเป้าหมายหมายความว่าเป้าหมายจะมองเห็นได้
ต่อสิ่งที่ผู้เรียกมาโครระบุไว้ในแอตทริบิวต์ visibility
ของมาโคร
รวมถึงแพ็กเกจของผู้เรียกมาโครเอง ตลอดจนโค้ดของมาโครเอง
อีกวิธีหนึ่งในการพิจารณาคือระดับการเข้าถึงของมาโครจะกำหนดว่าใคร (นอกเหนือจากตัวมาโครเอง) ที่จะเห็นเป้าหมายที่ส่งออกจากมาโคร
# tool/BUILD
...
some_rule(
name = "some_tool",
visibility = ["//macro:__pkg__"],
)
# macro/macro.bzl
def _impl(name, visibility):
cc_library(
name = name + "_helper",
...
# No visibility passed in. Same as passing `visibility = None` or
# `visibility = ["//visibility:private"]`. Visible to the //macro
# package only.
)
cc_binary(
name = name + "_exported",
deps = [
# Allowed because we're also in //macro. (Targets in any other
# instance of this macro, or any other macro in //macro, can see it
# too.)
name + "_helper",
# Allowed by some_tool's visibility, regardless of what BUILD file
# we're called from.
"//tool:some_tool",
],
...
visibility = visibility,
)
my_macro = macro(implementation = _impl, ...)
# pkg/BUILD
load("//macro:macro.bzl", "my_macro")
...
my_macro(
name = "foo",
...
)
some_rule(
...
deps = [
# Allowed, its visibility is ["//pkg:__pkg__", "//macro:__pkg__"].
":foo_exported",
# Disallowed, its visibility is ["//macro:__pkg__"] and
# we are not in //macro.
":foo_helper",
]
)
หากมีการเรียกใช้ my_macro
ด้วย visibility = ["//other_pkg:__pkg__"]
หรือหากแพ็กเกจ //pkg
ตั้งค่า default_visibility
เป็นค่าดังกล่าว ก็จะใช้ //pkg:foo_exported
ภายใน //other_pkg/BUILD
หรือภายในมาโครที่กำหนดไว้ใน //other_pkg:defs.bzl
ได้เช่นกัน แต่ //pkg:foo_helper
จะยังคงได้รับการป้องกัน
มาโครสามารถประกาศว่าเป้าหมายจะมองเห็นได้ในแพ็กเกจเพื่อนโดยการส่ง
visibility = ["//some_friend:__pkg__"]
(สำหรับเป้าหมายภายใน) หรือ
visibility = visibility + ["//some_friend:__pkg__"]
(สำหรับเป้าหมายที่ส่งออก)
โปรดทราบว่าการประกาศเป้าหมายที่มีระดับการเข้าถึงเป็นสาธารณะ (visibility = ["//visibility:public"]
) ในมาโครถือเป็นรูปแบบที่ไม่ควรทำ เนื่องจากจะทำให้ทุกแพ็กเกจมองเห็นเป้าหมายได้โดยไม่มีเงื่อนไข แม้ว่าผู้เรียกจะระบุระดับการเข้าถึงที่จำกัดกว่าก็ตาม
การตรวจสอบระดับการเข้าถึงทั้งหมดจะดำเนินการโดยอ้างอิงมาโครสัญลักษณ์ที่ทำงานอยู่ภายในสุดในปัจจุบัน อย่างไรก็ตาม มีกลไกการมอบสิทธิ์ระดับการมองเห็น กล่าวคือ หากมาโครส่งป้ายกำกับเป็นค่าแอตทริบิวต์ไปยังมาโครภายใน ระบบจะตรวจสอบการใช้ป้ายกำกับในมาโครภายในโดยอ้างอิงมาโครภายนอก ดูรายละเอียดเพิ่มเติมได้ที่หน้าการมองเห็น
โปรดทราบว่ามาโครเดิมจะโปร่งใสอย่างสมบูรณ์ต่อระบบการมองเห็น และทำงานราวกับว่าตำแหน่งของมาโครคือไฟล์ BUILD หรือมาโครเชิงสัญลักษณ์ ที่เรียกใช้มาโคร
Finalizer และระดับการมองเห็น
เป้าหมายที่ประกาศในตัวสรุปกฎ นอกเหนือจากการดูเป้าหมายตาม กฎการมองเห็นมาโครสัญลักษณ์ปกติแล้ว ยังดูเป้าหมายทั้งหมดที่ มองเห็นได้ในแพ็กเกจของเป้าหมายตัวสรุปได้ด้วย
ซึ่งหมายความว่าหากคุณย้ายข้อมูลมาโครเดิมที่อิงตาม native.existing_rules()
ไปยัง
Finalizer เป้าหมายที่ประกาศโดย Finalizer จะยังคงเห็น
การอ้างอิงเดิมของตน
อย่างไรก็ตาม โปรดทราบว่าคุณสามารถประกาศเป้าหมายในมาโครเชิงสัญลักษณ์
เพื่อให้เป้าหมายของ Finalizer ไม่เห็นเป้าหมายนั้นภายใต้ระบบการมองเห็นได้ แม้ว่า Finalizer จะตรวจสอบแอตทริบิวต์ของเป้าหมายได้โดยใช้
native.existing_rules()
เลือก
หากแอตทริบิวต์เป็น configurable
(ค่าเริ่มต้น) และค่าของแอตทริบิวต์ไม่ใช่ None
ฟังก์ชันการใช้งานมาโครจะเห็นค่าแอตทริบิวต์ที่ห่อหุ้ม
ใน select
ที่ไม่สำคัญ ซึ่งจะช่วยให้ผู้เขียนมาโครตรวจพบข้อบกพร่องได้ง่ายขึ้น
ในกรณีที่ไม่ได้คาดการณ์ว่าค่าแอตทริบิวต์อาจเป็น select
ตัวอย่างเช่น ลองพิจารณามาโครต่อไปนี้
my_macro = macro(
attrs = {"deps": attr.label_list()}, # configurable unless specified otherwise
implementation = _my_macro_impl,
)
หากเรียกใช้ my_macro
ด้วย deps = ["//a"]
จะทำให้มีการเรียกใช้ _my_macro_impl
โดยตั้งค่าพารามิเตอร์ deps
เป็น select({"//conditions:default":
["//a"]})
หากการดำเนินการนี้ทำให้ฟังก์ชันการติดตั้งใช้งานล้มเหลว (เช่น เนื่องจากโค้ดพยายามจัดทำดัชนีค่าตามที่ระบุใน deps[0]
ซึ่งไม่ได้รับอนุญาตสำหรับ select
) ผู้เขียนมาโครจะเลือกได้ว่าจะเขียนมาโครใหม่ให้ใช้เฉพาะการดำเนินการที่เข้ากันได้กับ select
หรือจะทำเครื่องหมายแอตทริบิวต์เป็นกำหนดค่าไม่ได้ (attr.label_list(configurable = False)
) ก็ได้ การดำเนินการอย่างหลังจะช่วยให้มั่นใจว่าผู้ใช้จะไม่ได้รับอนุญาตให้ส่งค่า select
เป้าหมายกฎจะย้อนกลับการเปลี่ยนรูปแบบนี้ และจัดเก็บ select
ที่ไม่สำคัญเป็นค่าแบบไม่มีเงื่อนไข ในตัวอย่างข้างต้น หาก _my_macro_impl
ประกาศเป้าหมายกฎ my_rule(..., deps = deps)
ระบบจะจัดเก็บ deps
ของเป้าหมายกฎนั้นเป็น ["//a"]
ซึ่งจะช่วยให้มั่นใจได้ว่า select
-wrapping จะไม่ทำให้ระบบจัดเก็บค่า select
ที่ไม่สำคัญในเป้าหมายทั้งหมดที่สร้างขึ้นโดยใช้มาโคร
หากค่าของแอตทริบิวต์ที่กำหนดค่าได้เป็น None
ระบบจะไม่ห่อค่าดังกล่าวใน
select
ซึ่งจะช่วยให้การทดสอบ เช่น my_attr == None
ยังคงทำงานได้ และเมื่อมีการส่งต่อแอตทริบิวต์ไปยังกฎที่มีค่าเริ่มต้นที่คำนวณแล้ว กฎจะทำงานอย่างถูกต้อง (กล่าวคือ ทำงานราวกับว่าไม่มีการส่งแอตทริบิวต์เลย) แอตทริบิวต์อาจไม่สามารถใช้ค่า None
ได้เสมอไป แต่จะใช้ได้กับประเภท attr.label()
และแอตทริบิวต์ที่ไม่บังคับที่รับค่ามา
Finalizers
ตัวสรุปกฎคือมาโครสัญลักษณ์พิเศษซึ่งจะได้รับการประเมินในขั้นตอนสุดท้ายของการโหลดแพ็กเกจ ไม่ว่าตำแหน่งในไฟล์ BUILD จะเป็นอย่างไร
หลังจากกำหนดเป้าหมายที่ไม่ใช่ตัวสรุปทั้งหมดแล้ว Finalizer จะเรียกใช้ native.existing_rules()
ได้ ซึ่งต่างจากมาโครสัญลักษณ์ทั่วไป โดยจะทำงานแตกต่างจากในมาโครเดิมเล็กน้อย นั่นคือจะแสดงผลเฉพาะชุดเป้าหมายของกฎที่ไม่ใช่ Finalizer Finalizer อาจยืนยันสถานะของชุดนั้นหรือ
กำหนดเป้าหมายใหม่
หากต้องการประกาศ Finalizer ให้เรียกใช้ macro()
โดยมี finalizer = True
ดังนี้
def _my_finalizer_impl(name, visibility, tags_filter):
for r in native.existing_rules().values():
for tag in r.get("tags", []):
if tag in tags_filter:
my_test(
name = name + "_" + r["name"] + "_finalizer_test",
deps = [r["name"]],
data = r["srcs"],
...
)
continue
my_finalizer = macro(
attrs = {"tags_filter": attr.string_list(configurable = False)},
implementation = _impl,
finalizer = True,
)
ความขี้เกียจ
สำคัญ: เรากำลังดำเนินการเพื่อใช้การขยายมาโครแบบเลื่อนเวลาและ การประเมิน ฟีเจอร์นี้ยังไม่พร้อมใช้งาน
ปัจจุบัน ระบบจะประเมินมาโครทั้งหมดทันทีที่โหลดไฟล์ BUILD ซึ่ง อาจส่งผลเสียต่อประสิทธิภาพของเป้าหมายในแพ็กเกจที่มีมาโครที่ไม่เกี่ยวข้องซึ่งมีค่าใช้จ่ายสูง ด้วย ในอนาคต มาโครสัญลักษณ์ที่ไม่ใช่ตัวสรุปจะได้รับการประเมินก็ต่อเมื่อจำเป็นสำหรับการสร้างเท่านั้น รูปแบบการตั้งชื่อคำนำหน้าจะช่วยให้ Bazel ระบุได้ว่าจะขยายมาโครใดเมื่อได้รับเป้าหมายที่ขอ
การแก้ปัญหาการย้ายข้อมูล
ต่อไปนี้คือปัญหาที่พบบ่อยในการย้ายข้อมูลและวิธีแก้ไข
- การเรียกใช้มาโครเวอร์ชันเดิม
glob()
ย้ายการเรียก glob()
ไปยังไฟล์ BUILD (หรือไปยังมาโครเดิมที่เรียกจากไฟล์ BUILD) และส่งค่า glob()
ไปยังมาโครสัญลักษณ์โดยใช้แอตทริบิวต์รายการป้ายกำกับ
# BUILD file
my_macro(
...,
deps = glob(...),
)
- มาโครเดิมมีพารามิเตอร์ที่ไม่ใช่ประเภท
attr
ของ Starlark ที่ถูกต้อง
ดึงตรรกะให้ได้มากที่สุดเท่าที่จะทำได้ลงในมาโครสัญลักษณ์ที่ซ้อนกัน แต่ให้มาโครระดับบนสุดเป็นมาโครเดิม
- มาโครเดิมเรียกใช้กฎที่สร้างเป้าหมายซึ่งละเมิดรูปแบบการตั้งชื่อ
ไม่เป็นไร เพียงแต่อย่าพึ่งพาเป้าหมายที่ "ละเมิด" ระบบจะเพิกเฉยต่อการตรวจสอบการตั้งชื่อ โดยไม่มีการแจ้งเตือน