หน้านี้จะครอบคลุมระบบระดับการเข้าถึง 2 ระบบของ Bazel ได้แก่ ระดับการเข้าถึงเป้าหมายและโหลดระดับการเข้าถึง
ระดับการเข้าถึงทั้ง 2 ประเภทช่วยให้นักพัฒนาซอฟต์แวร์คนอื่นๆ แยกแยะระหว่าง API สาธารณะของไลบรารีกับรายละเอียดการใช้งานได้ และช่วยบังคับใช้โครงสร้างเมื่อพื้นที่ทํางานของคุณเติบโตขึ้น นอกจากนี้ คุณยังสามารถใช้ระดับการเข้าถึงเมื่อเลิกใช้งาน API สาธารณะเพื่ออนุญาตให้ผู้ใช้ปัจจุบันพร้อมปฏิเสธ API ใหม่
ระดับการเข้าถึงเป้าหมาย
ระดับการเข้าถึงเป้าหมายจะควบคุมผู้ที่อาจพึ่งพาเป้าหมายของคุณ กล่าวคือ ผู้ที่อาจใช้ป้ายกํากับเป้าหมายภายในแอตทริบิวต์ เช่น deps
เป้าหมาย A
จะแสดงแก่เป้าหมาย B
หากอยู่ในแพ็กเกจเดียวกัน หรือหาก A
ให้สิทธิ์เข้าถึงแพ็กเกจของ B
ดังนั้นแพ็กเกจก็เป็นหน่วยแบบละเอียดในการตัดสินใจว่าจะอนุญาตการเข้าถึงหรือไม่ หาก B
ต้องใช้ A
แต่ B
ไม่แสดง A
การพยายามสร้าง B
จะไม่สําเร็จระหว่างการวิเคราะห์
โปรดทราบว่าการให้สิทธิ์ระดับการเข้าถึงแพ็กเกจไม่ได้ทําให้แพ็กเกจย่อยมองเห็น ได้ โปรดดูรายละเอียดเพิ่มเติมเกี่ยวกับแพ็กเกจและแพ็กเกจย่อยที่หัวข้อแนวคิดและคําศัพท์
สําหรับต้นแบบ คุณสามารถปิดใช้การบังคับใช้ระดับการเข้าถึงเป้าหมายได้โดยการตั้งค่าสถานะ --check_visibility=false
การดําเนินการนี้จะไม่เกิดขึ้นสําหรับการใช้งานจริงในโค้ดที่ส่ง
วิธีหลักในการควบคุมระดับการเข้าถึงคือใช้แอตทริบิวต์ visibility
กับเป้าหมายกฎ ส่วนนี้อธิบายรูปแบบแอตทริบิวต์นี้ของแอตทริบิวต์นี้และวิธีกําหนดระดับการเข้าถึงเป้าหมาย
ข้อกําหนดด้านการแสดงผล
เป้าหมายกฎทั้งหมดมีแอตทริบิวต์ visibility
ที่ใช้รายการป้ายกํากับ ป้ายกํากับแต่ละรายการจะมีรูปแบบใดรูปแบบหนึ่งต่อไปนี้ ยกเว้นรูปแบบสุดท้าย ตัวยึดตําแหน่งเหล่านี้เป็นเพียงตัวยึดตําแหน่งที่เป็นไวยากรณ์ซึ่งไม่ตรงกับเป้าหมายจริงใดๆ
"//visibility:public"
: ให้สิทธิ์เข้าถึงแพ็กเกจทั้งหมด (ห้ามใช้ร่วมกับข้อกําหนดอื่นๆ)"//visibility:private"
: ไม่ได้ให้สิทธิ์เข้าถึงเพิ่มเติม มีเฉพาะเป้าหมายในแพ็กเกจนี้เท่านั้นที่จะใช้เป้าหมายนี้ได้ (ต้องไม่รวมกับข้อกําหนดอื่นๆ)"//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
ของแต่ละเป้าหมาย ซึ่งทําให้อ่านง่ายขึ้นและป้องกันไม่ให้รายการซิงค์กัน
ระดับการเข้าถึงกฎของกฎ
ระดับการเข้าถึงของเป้าหมายกฎคือ
ค่าของแอตทริบิวต์
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 ที่ไม่ได้สะกดในไฟล์ BUILD
แต่โดยพื้นฐานแล้วกับอินสแตนซ์ทั้งหมดของกฎนั้น เช่น กฎ cc_library
อาจสร้างทรัพยากร Dependency จากเป้าหมายกฎแต่ละข้อไปยังเป้าหมายปฏิบัติการซึ่งแสดงถึงคอมไพเลอร์ C++
ในปัจจุบัน ระดับการเข้าถึงนี้อาศัยทรัพยากร Dependency เหล่านี้เหมือนกับทรัพยากร Dependency อื่นๆ ซึ่งหมายความว่าเป้าหมายที่ต้องพึ่งพา (เช่น คอมไพเลอร์ C++) ต้องแสดงต่อทุกอินสแตนซ์ของกฎ ซึ่งในทางปฏิบัติหมายความว่าเป้าหมายต้องมีระดับการเข้าถึงแบบสาธารณะ
คุณสามารถเปลี่ยนลักษณะการทํางานนี้ได้โดยการตั้งค่า --incompatible_visibility_private_attributes_at_definition
เมื่อเปิดใช้ เป้าหมายที่ต้องการจะเห็นเฉพาะกฎที่ประกาศการขึ้นต่อกันแบบโดยนัยเท่านั้น กล่าวคือ แพ็กเกจดังกล่าวต้องปรากฏกับแพ็กเกจที่มีไฟล์ .bzl
ซึ่งกําหนดกฎ ในตัวอย่างของเรา คอมไพเลอร์ C++ อาจเป็นแบบส่วนตัวตราบใดที่อยู่ในแพ็กเกจเดียวกันกับคําจํากัดความของกฎ 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()
จะสามารถโหลดได้จากทุกที่ในพื้นที่ทํางาน คุณควรเพิ่ม 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
ไม่ได้ หากต้องการใช้รายการที่อนุญาตเดียวกันทั้งกับระดับการเข้าถึงและระดับการเข้าถึงเป้าหมาย คุณควรย้ายรายการข้อมูลจําเพาะของแพ็กเกจเป็นไฟล์ .bzl ซึ่งการประกาศทั้ง 2 ประเภทอาจอ้างอิงกัน การสร้างตัวอย่างในระดับการมองเห็นปัจจัยด้านบน คุณอาจเขียนว่า
# //mylib/BUILD
load(":internal_defs", "clients")
package_group(
name = "my_pkg_grp",
packages = clients,
)
วิธีนี้จะใช้ได้ต่อเมื่อรายการไม่มีข้อมูลจําเพาะของแพ็กเกจเชิงลบ
การป้องกันสัญลักษณ์แต่ละรายการ
ไม่สามารถโหลดสัญลักษณ์ Starlark ที่มีชื่อขึ้นต้นด้วยขีดล่างจากไฟล์อื่นได้ ซึ่งช่วยให้สร้างสัญลักษณ์ส่วนตัวได้อย่างง่ายดาย แต่ไม่อนุญาตให้แชร์สัญลักษณ์เหล่านี้กับชุดไฟล์ที่เชื่อถือได้แบบจํากัด ในทางกลับกัน ระดับการเข้าถึงการโหลดจะช่วยให้คุณควบคุมสิ่งที่แพ็กเกจอื่นๆ อาจเห็น .bzl file
ได้ แต่ไม่อนุญาตให้โหลดสัญลักษณ์ที่ไม่มีขีดล่าง
แต่โชคดีที่คุณสามารถใช้ฟีเจอร์ทั้ง 2 อย่างนี้ร่วมกันเพื่อให้มีการควบคุมแบบละเอียด
# //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
ขุยผ้าของ Bzl-visible
มี Linth Linux Builder ที่แสดงการแจ้งเตือนหากผู้ใช้โหลดไฟล์จากไดเรกทอรีชื่อ internal
หรือ private
เมื่อไฟล์ของผู้ใช้ไม่ได้อยู่ในตัวระดับบนสุดของไดเรกทอรีนั้น Linux จะใช้พิจารณาฟีเจอร์ระดับการเข้าถึงโหลดล่วงหน้าและไม่จําเป็นในพื้นที่ทํางานที่ไฟล์ .bzl
ประกาศระดับการมองเห็น