หน้านี้กล่าวถึงระบบการมองเห็น 2 ระบบของ Bazel ได้แก่ ระดับการเข้าถึงเป้าหมายและการโหลดการแสดงผล
การเปิดเผยทั้ง 2 ประเภทจะช่วยให้นักพัฒนาซอฟต์แวร์รายอื่นแยกแยะความแตกต่างระหว่าง API สาธารณะของไลบรารีและรายละเอียดการใช้งาน และช่วยบังคับใช้โครงสร้าง เมื่อพื้นที่ทำงานเติบโต คุณยังใช้การเปิดเผยได้เมื่อเลิกใช้งานสาธารณะ API เพื่ออนุญาตผู้ใช้ปัจจุบันขณะปฏิเสธผู้ใช้รายใหม่
ระดับการเข้าถึงเป้าหมาย
ระดับการเข้าถึงเป้าหมายจะควบคุมผู้ที่อาจอิงตามเป้าหมายของคุณ กล่าวคือ ผู้ที่อาจ
ใช้ป้ายกำกับของเป้าหมายภายในแอตทริบิวต์ เช่น deps
A
เป้าหมายจะมองเห็นได้ต่อ B
เป้าหมายหากอยู่ในแพ็กเกจเดียวกัน หรือหาก
A
ให้สิทธิ์ระดับการเข้าถึงแพ็กเกจของ B
ดังนั้น แพ็กเกจคือหน่วยของ
รายละเอียดในการตัดสินใจว่าจะอนุญาตการเข้าถึงหรือไม่ หาก B
ต้องพึ่งพา A
แต่ B
ไม่เห็น A
ดังนั้นความพยายามใดๆ ในการสร้าง B
จะล้มเหลวระหว่าง
การวิเคราะห์
โปรดทราบว่าการให้สิทธิ์ระดับการเข้าถึงแพ็กเกจไม่ได้เป็นการให้สิทธิ์ระดับการเข้าถึง ไว้ในแพ็กเกจย่อย ดูรายละเอียดเพิ่มเติมเกี่ยวกับแพ็กเกจและแพ็กเกจย่อยได้ที่ แนวคิดและคำศัพท์
สำหรับการสร้างต้นแบบ คุณสามารถปิดการบังคับใช้ระดับการเข้าถึงเป้าหมายได้โดยตั้งค่า
แจ้งว่า --check_visibility=false
ซึ่งไม่ควรนำไปใช้สำหรับการใช้งานจริงใน
รหัสที่ส่ง
วิธีหลักในการควบคุมระดับการมองเห็นคือ
แอตทริบิวต์ visibility
เปิดอยู่
เป้าหมายกฎ ส่วนนี้จะอธิบายรูปแบบของแอตทริบิวต์นี้และวิธี
กำหนดการมองเห็นของเป้าหมาย
ข้อกำหนดเกี่ยวกับระดับการเข้าถึง
เป้าหมายกฎทั้งหมดมีแอตทริบิวต์ visibility
ที่ใช้รายการป้ายกำกับ ชิ้น
ป้ายกำกับ มีรูปแบบอย่างใดอย่างหนึ่งต่อไปนี้ ยกเว้นรูปแบบสุดท้าย
เป็นเพียงตัวยึดตำแหน่งเชิงไวยากรณ์ที่ไม่สอดคล้องกับเป้าหมายจริงใดๆ
"//visibility:public"
: ให้สิทธิ์เข้าถึงแพ็กเกจทั้งหมด (ไม่สามารถรวมได้ และข้อกำหนดอื่นใด)"//visibility:private"
: ไม่ให้สิทธิ์เข้าถึงเพิ่มเติม เป้าหมายเท่านั้น ในแพ็กเกจนี้สามารถใช้เป้าหมายนี้ได้ (ไม่สามารถใช้ร่วมกับรายการอื่นๆ specification.)"//foo/bar:__pkg__"
: ให้สิทธิ์เข้าถึง//foo/bar
(แต่ไม่ใช่ แพ็กเกจย่อย)"//foo/bar:__subpackages__"
: ให้สิทธิ์เข้าถึง//foo/bar
และทั้งหมด โดยตรงและโดยอ้อม"//some_pkg:my_package_group"
: ให้สิทธิ์เข้าถึงแพ็กเกจทั้งหมดที่ เป็นส่วนหนึ่งของpackage_group
ที่กำหนด- กลุ่มแพ็กเกจใช้
ไวยากรณ์ที่แตกต่างกันสำหรับ
โดยระบุแพ็กเกจ ภายในกลุ่มแพ็กเกจ แบบฟอร์ม
"//foo/bar:__pkg__"
และ"//foo/bar:__subpackages__"
ตามลำดับ แทนที่ด้วย"//foo/bar"
และ"//foo/bar/..."
ในทำนองเดียวกัน"//visibility:public"
และ"//visibility:private"
เหลือแค่"public"
และ"private"
- กลุ่มแพ็กเกจใช้
ไวยากรณ์ที่แตกต่างกันสำหรับ
โดยระบุแพ็กเกจ ภายในกลุ่มแพ็กเกจ แบบฟอร์ม
ตัวอย่างเช่น หาก //some/package:mytarget
ตั้งค่า visibility
เป็น
[":__subpackages__", "//tests:__pkg__"]
จากนั้นก็สามารถใช้โดยเป้าหมายใดก็ได้
ซึ่งเป็นส่วนหนึ่งของโครงสร้างซอร์ส //some/package/...
รวมถึงเป้าหมายที่กำหนดไว้
ใน //tests/BUILD
แต่ไม่ใช่เป้าหมายที่กำหนดไว้ใน //tests/integration/BUILD
แนวทางปฏิบัติแนะนำ: หากต้องการให้เป้าหมายหลายรายการแสดงในชุดเดียวกัน
ให้ใช้ package_group
แทนการทำซ้ำรายการในแต่ละแพ็กเกจ
แอตทริบิวต์ visibility
ของเป้าหมาย ซึ่งจะช่วยเพิ่มความอ่านง่ายและป้องกัน
หลายรายการพร้อมกันไม่ให้ซิงค์กัน
แนวทางปฏิบัติแนะนำ: เมื่อให้สิทธิ์ระดับการเข้าถึงแก่โปรเจ็กต์ของทีมอื่น ให้เลือก
__subpackages__
เมื่อ __pkg__
เพื่อหลีกเลี่ยงการเลิกใช้งานโดยไม่จำเป็น
พัฒนาโครงการและเพิ่มแพ็กเกจย่อยใหม่
ระดับการเข้าถึงเป้าหมายของกฎ
ระดับการเข้าถึงของเป้าหมายกฎคือ
ค่าของแอตทริบิวต์
visibility
หากตั้งค่าไว้ หรืออื่นๆค่าของแอตทริบิวต์
default_visibility
อาร์กิวเมนต์ของคำสั่งpackage
ใน ไฟล์BUILD
ของเป้าหมาย หากมีการประกาศดังกล่าวอยู่ หรืออื่นๆ//visibility:private
แนวทางปฏิบัติแนะนำ: หลีกเลี่ยงการตั้งค่า default_visibility
เป็นสาธารณะ อาจจะเป็น
สะดวกในการสร้างต้นแบบหรือในโค้ดเบสขนาดเล็ก แต่การเกิด
การสร้างเป้าหมายสาธารณะจะเพิ่มขึ้นเมื่อโค้ดเบสเติบโตขึ้น เราน่าจะดีกว่า
ระบุอย่างชัดเจนว่าเป้าหมายใดเป็นส่วนหนึ่งของอินเทอร์เฟซสาธารณะของแพ็กเกจ
ตัวอย่าง
ไฟล์ //frobber/bin/BUILD
:
# This target is visible to everyone
cc_binary(
name = "executable",
visibility = ["//visibility:public"],
deps = [":library"],
)
# This target is visible only to targets declared in the same package
cc_library(
name = "library",
# No visibility -- defaults to private since no
# package(default_visibility = ...) was used.
)
# This target is visible to targets in package //object and //noun
cc_library(
name = "subject",
visibility = [
"//noun:__pkg__",
"//object:__pkg__",
],
)
# See package group "//frobber:friends" (below) for who can
# access this target.
cc_library(
name = "thingy",
visibility = ["//frobber:friends"],
)
ไฟล์ //frobber/BUILD
:
# This is the package group declaration to which target
# //frobber/bin:thingy refers.
#
# Our friends are packages //frobber, //fribber and any
# subpackage of //fribber.
package_group(
name = "friends",
packages = [
"//fribber/...",
"//frobber",
],
)
การเปิดเผยเป้าหมายไฟล์ที่สร้างขึ้น
เป้าหมายไฟล์ที่สร้างขึ้นมีระดับการเข้าถึงเดียวกับเป้าหมายกฎที่ ก็ช่วยสร้างสิ่งนั้นขึ้นมา
การเปิดเผยเป้าหมายไฟล์ต้นฉบับ
คุณสามารถกำหนดการมองเห็นเป้าหมายไฟล์ต้นฉบับได้โดยการเรียกใช้
exports_files
เมื่อไม่มี visibility
ส่งผ่านอาร์กิวเมนต์ไปยัง exports_files
จะทำให้การเปิดเผยเป็นสาธารณะ
ไม่สามารถใช้ exports_files
เพื่อลบล้างการเปิดเผยของไฟล์ที่สร้างขึ้น
สำหรับเป้าหมายไฟล์ต้นฉบับที่ไม่ปรากฏในการเรียกไปยัง exports_files
ค่า
ระดับการมองเห็นจะขึ้นอยู่กับค่าของการแจ้ง
--incompatible_no_implicit_file_export
:
หากตั้งค่าไว้ ระดับการแชร์จะเป็นแบบส่วนตัว
ไม่เช่นนั้น ระบบจะใช้ลักษณะการทำงานแบบเดิม: ระดับการเข้าถึงจะเหมือนกับ
default_visibility
ของไฟล์BUILD
หรือ "ส่วนตัว" หากระดับการเข้าถึงเริ่มต้นคือ ไม่ได้ระบุ
หลีกเลี่ยงการใช้ลักษณะการทำงานเดิม เขียน exports_files
เสมอ
เมื่อใดก็ตามที่เป้าหมายไฟล์แหล่งที่มาจำเป็นต้องมีระดับการเข้าถึงแบบไม่เป็นส่วนตัว
แนวทางปฏิบัติแนะนำ: เมื่อเป็นไปได้ คุณควรแสดงเป้าหมายกฎแทน
ไฟล์ต้นฉบับ เช่น แทนที่จะเรียก exports_files
ในไฟล์ .java
รวมไฟล์ในเป้าหมาย java_library
แบบไม่เป็นส่วนตัว โดยทั่วไป เป้าหมายกฎ
ควรอ้างอิงโดยตรงเฉพาะไฟล์ต้นฉบับที่อยู่ในแพ็กเกจเดียวกันเท่านั้น
ตัวอย่าง
ไฟล์ //frobber/data/BUILD
:
exports_files(["readme.txt"])
ไฟล์ //frobber/bin/BUILD
:
cc_binary(
name = "my-program",
data = ["//frobber/data:readme.txt"],
)
ระดับการเข้าถึงการตั้งค่าการกำหนดค่า
ที่ผ่านมา Bazel ไม่ได้บังคับใช้การแสดงผลสำหรับ
เป้าหมาย config_setting
ที่
ที่อ้างอิงในคีย์ของ select()
มี
เป็นการแจ้ง 2 ข้อที่จะนำลักษณะการทำงานแบบเดิมนี้ออก
--incompatible_enforce_config_setting_visibility
เปิดใช้การตรวจสอบการเปิดเผยสำหรับเป้าหมายเหล่านี้ ในการย้ายข้อมูล จะทำให้config_setting
ที่ไม่ได้ระบุvisibility
เป็น ถือเป็นสาธารณะ (โดยไม่คำนึงถึงdefault_visibility
ระดับแพ็กเกจ)--incompatible_config_setting_private_default_visibility
ทำให้config_setting
ที่ไม่ได้ระบุvisibility
ดำเนินการตามคำสั่งdefault_visibility
ของแพ็กเกจและการสำรองข้อมูลแบบส่วนตัว เช่นเดียวกับเป้าหมายกฎอื่นๆ เราจะไม่ดำเนินการหาก ไม่ได้ตั้งค่า--incompatible_enforce_config_setting_visibility
หลีกเลี่ยงการใช้ลักษณะการทำงานเดิม config_setting
ใดๆ ที่มีวัตถุประสงค์เพื่อ
ใช้ภายนอกแพ็กเกจปัจจุบันควรมี visibility
ที่ชัดเจนหาก
แพ็กเกจไม่ได้ระบุ default_visibility
ที่เหมาะสมอยู่แล้ว
ระดับการเข้าถึงเป้าหมายกลุ่มแพ็กเกจ
เป้าหมาย package_group
ไม่มีแอตทริบิวต์ visibility
เสมอ
ปรากฏแบบสาธารณะ
ระดับการเข้าถึงทรัพยากร Dependency โดยนัย
กฎบางข้อมีทรัพยากร Dependency แบบโดยนัย ดังนี้
ทรัพยากร Dependency ที่ไม่ได้ระบุไว้ในไฟล์ BUILD
แต่อยู่ในรูปแบบ
ในทุกอินสแตนซ์ของกฎ ตัวอย่างเช่น กฎ cc_library
อาจสร้าง
การขึ้นต่อกันโดยนัยจากเป้าหมายกฎแต่ละข้อไปยังเป้าหมายที่ดำเนินการได้
ซึ่งแสดงถึงคอมไพเลอร์ C++
ระดับการเข้าถึงของทรัพยากร Dependency โดยนัยดังกล่าวจะได้รับการตรวจสอบตาม
แพ็กเกจที่มีไฟล์ .bzl
ซึ่งมีการนิยามกฎ (หรือองค์ประกอบ) ไว้ ใน
ในตัวอย่างของเรา คอมไพเลอร์ C++ อาจเป็นแบบส่วนตัวได้ตราบใดที่ยังอยู่
เป็นคำจำกัดความของกฎ cc_library
เป็นตัวเลือกสำรอง หาก
การขึ้นต่อกันโดยปริยายไม่ปรากฏจากคำจำกัดความ แต่ได้รับการตรวจสอบกับ
ตามเป้าหมาย cc_library
หากต้องการจำกัดการใช้กฎสำหรับแพ็กเกจบางรายการ ให้ใช้ โหลดการแสดงผลแทน
โหลดระดับการมองเห็น
โหลดระดับการมองเห็นควบคุมว่าสามารถโหลดไฟล์ .bzl
จากที่อื่นหรือไม่
BUILD
หรือ .bzl
ไฟล์ที่อยู่นอกแพ็กเกจปัจจุบัน
ในลักษณะเดียวกับที่ระดับการเข้าถึงเป้าหมายปกป้องซอร์สโค้ดที่ห่อหุ้มอยู่
ตามเป้าหมาย ระดับการมองเห็นโหลดช่วยปกป้องลอจิกบิลด์ที่ห่อหุ้มโดย .bzl
ตัวอย่างเช่น ผู้เขียนไฟล์ BUILD
อาจต้องการคํานึงถึงรายการที่ซ้ำซ้อน
กำหนดเป้าหมายเป็นมาโครในไฟล์ .bzl
ไม่มีการป้องกันของน้ำหนักบรรทุก
การมองเห็นอาจพบว่ามีการใช้มาโครที่ผู้ทำงานร่วมกันคนอื่นๆ ใช้ซ้ำใน
พื้นที่ทำงานเดียวกัน ดังนั้นการแก้ไขมาโครจะทำให้ทีมอื่นๆ ไม่ทำงาน งานสร้าง
โปรดทราบว่าไฟล์ .bzl
อาจมีหรือไม่มีเป้าหมายไฟล์ต้นฉบับที่เกี่ยวข้อง
มิฉะนั้น จะไม่มีการรับประกันว่าระดับการมองเห็นโหลดและเป้าหมาย
เห็นพร้อมกัน ซึ่งหมายความว่า ไฟล์ BUILD
เดียวกันอาจโหลด
.bzl
ไฟล์ แต่ไม่ได้แสดงอยู่ใน srcs
ของ filegroup
หรือในทางกลับกันก็ได้ ซึ่งอาจทำให้เกิดปัญหากับกฎที่ต้องการใช้
.bzl
ไฟล์เป็นซอร์สโค้ด เช่น สำหรับการสร้างหรือการทดสอบเอกสาร
สำหรับการสร้างต้นแบบ คุณอาจปิดการบังคับใช้ระดับการเข้าถึงโหลดได้โดยการตั้งค่า
--check_bzl_visibility=false
เช่นเดียวกับ --check_visibility=false
โค้ดนี้ควร
ไม่มีการดำเนินการสำหรับโค้ดที่ส่ง
ระดับการมองเห็นโหลดพร้อมให้บริการตั้งแต่ Bazel 6.0
การประกาศระดับการเข้าถึงโหลด
หากต้องการตั้งค่าการเปิดเผยการโหลดของไฟล์ .bzl
โปรดเรียกใช้
visibility()
จากภายในไฟล์
อาร์กิวเมนต์ของ visibility()
คือรายการข้อมูลจำเพาะของแพ็กเกจ เช่นเดียวกับ
แอตทริบิวต์ packages
ของ
package_group
แต่ visibility()
ไม่ยอมรับแพ็กเกจเชิงลบ
การเรียก visibility()
จะต้องทำเพียงครั้งเดียวต่อไฟล์ ที่ระดับบนสุด (ไม่ใช่
ภายในฟังก์ชัน) และควรจะต่อท้ายคำสั่ง load()
ทันที
การเปิดเผยการโหลดเริ่มต้นจะเป็นแบบสาธารณะเสมอ ซึ่งต่างจากการเปิดเผยเป้าหมาย ไฟล์
ที่ไม่เรียกใช้ visibility()
จะสามารถโหลดได้จากทุกที่ใน
Google Workspace ได้อย่างเต็มประสิทธิภาพ ควรเพิ่ม visibility("private")
ไว้บนสุด
ไฟล์ .bzl
ใหม่ที่ไม่ได้มีจุดประสงค์เพื่อการใช้งานนอกแพ็กเกจโดยเฉพาะ
ตัวอย่าง
# //mylib/internal_defs.bzl
# Available to subpackages and to mylib's tests.
visibility(["//mylib/...", "//tests/mylib/..."])
def helper(...):
...
# //mylib/rules.bzl
load(":internal_defs.bzl", "helper")
# Set visibility explicitly, even though public is the default.
# Note the [] can be omitted when there's only one entry.
visibility("public")
myrule = rule(
...
)
# //someclient/BUILD
load("//mylib:rules.bzl", "myrule") # ok
load("//mylib:internal_defs.bzl", "helper") # error
...
โหลดแนวทางปฏิบัติด้านระดับการเข้าถึง
ส่วนนี้จะอธิบายเคล็ดลับในการจัดการการประกาศระดับการมองเห็นโหลด
การแยกการแสดงผล
เมื่อไฟล์ .bzl
หลายไฟล์ควรมีระดับการเข้าถึงเดียวกัน ก็อาจมีประโยชน์ดังนี้
ให้รวมข้อมูลจำเพาะของแพ็กเกจนั้นๆ ไว้ในรายการร่วมด้วย เช่น
# //mylib/internal_defs.bzl
visibility("private")
clients = [
"//foo",
"//bar/baz/...",
...
]
# //mylib/feature_A.bzl
load(":internal_defs.bzl", "clients")
visibility(clients)
...
# //mylib/feature_B.bzl
load(":internal_defs.bzl", "clients")
visibility(clients)
...
วิธีนี้จะช่วยป้องกันไม่ให้ไฟล์ .bzl
ต่างๆ เอียงโดยไม่ตั้งใจ
ระดับการเข้าถึง นอกจากนี้ยังอ่านได้ง่ายขึ้นเมื่อรายการ clients
มีขนาดใหญ่
การเปิดเผยการเขียน
บางครั้งคุณอาจต้องเห็นไฟล์ .bzl
ในรายการที่อนุญาต
ซึ่งประกอบด้วยรายการที่อนุญาตย่อยหลายรายการ ซึ่งเปรียบได้กับวิธีการ
package_group
สามารถรวม package_group
อื่นๆ ผ่าน
includes
สมมติว่าคุณจะเลิกใช้มาโครที่ใช้กันอย่างแพร่หลาย คุณต้องการให้มองเห็นได้เท่านั้น ทั้งกับผู้ใช้ปัจจุบันและแพ็กเกจที่ทีมของคุณเป็นเจ้าของ โดยคุณอาจเขียนข้อความดังนี้
# //mylib/macros.bzl
load(":internal_defs.bzl", "our_packages")
load("//some_big_client:defs.bzl", "their_remaining_uses")
# List concatenation. Duplicates are fine.
visibility(our_packages + their_remaining_uses)
กรองข้อมูลที่ซ้ำกันออกด้วยกลุ่มแพ็กเกจ
ซึ่งแตกต่างจากการเปิดเผยเป้าหมาย คุณไม่สามารถกำหนดการแสดงการโหลดในรูปของ
package_group
หากต้องการนำรายการที่อนุญาตเดียวกันไปใช้กับเป้าหมายทั้ง 2 รายการ
ระดับการมองเห็นและการโหลด จะเป็นการดีที่สุดที่จะย้ายรายการแพ็กเกจ
เป็นไฟล์ .bzl โดยที่การประกาศทั้ง 2 ประเภทอาจหมายถึง
ได้ ต่อยอดจากตัวอย่างในการแสดงปัจจัย
ด้านบน คุณอาจเขียนว่า
# //mylib/BUILD
load(":internal_defs", "clients")
package_group(
name = "my_pkg_grp",
packages = clients,
)
วิธีนี้จะใช้ได้เฉพาะเมื่อรายการไม่มีแพ็กเกจเชิงลบ
การปกป้องสัญลักษณ์แต่ละตัว
โหลดสัญลักษณ์ Starlark ที่ชื่อเริ่มต้นด้วยเครื่องหมายขีดล่างไม่ได้
อีกไฟล์หนึ่ง ซึ่งช่วยให้ง่ายต่อการสร้างสัญลักษณ์ส่วนตัว แต่ไม่อนุญาตให้
คุณสามารถแชร์สัญลักษณ์เหล่านี้กับไฟล์ที่เชื่อถือได้บางส่วน ในอีกทาง
การแสดงผลการโหลดช่วยให้คุณควบคุม ว่าแพ็กเกจอื่นๆ อาจเห็น
.bzl file
แต่ไม่อนุญาตให้คุณป้องกันสัญลักษณ์ที่ไม่มีเครื่องหมายขีดล่างจาก
กำลังโหลด
โชคดีที่คุณสามารถรวมคุณลักษณะทั้งสองนี้เข้าด้วยกันเพื่อให้เป็นการควบคุมแบบละเอียด
# //mylib/internal_defs.bzl
# Can't be public, because internal_helper shouldn't be exposed to the world.
visibility("private")
# Can't be underscore-prefixed, because this is
# needed by other .bzl files in mylib.
def internal_helper(...):
...
def public_util(...):
...
# //mylib/defs.bzl
load(":internal_defs", "internal_helper", _public_util="public_util")
visibility("public")
# internal_helper, as a loaded symbol, is available for use in this file but
# can't be imported by clients who load this file.
...
# Re-export public_util from this file by assigning it to a global variable.
# We needed to import it under a different name ("_public_util") in order for
# this assignment to be legal.
public_util = _public_util
Lint บิลด์การมองเห็น bzl
มีผ้าย่อยของบิลด์
ที่ให้คำเตือนหากผู้ใช้โหลดไฟล์จากไดเรกทอรีชื่อ internal
หรือ private
เมื่อไฟล์ของผู้ใช้ไม่ได้อยู่ใต้ไฟล์หลักของไฟล์ดังกล่าว
ไดเรกทอรี โปรแกรม Lint นี้เกิดขึ้นก่อนฟีเจอร์การเปิดเผยการโหลดและไม่จำเป็นใน
พื้นที่ทำงานที่ไฟล์ .bzl
ประกาศระดับการเข้าถึง