顯示設定

回報問題 查看原始碼 夜間 7.4 ,直接在 Google Cloud 控制台實際操作。 7.3 · 7.2 · 7.1 · 7.0 · 6.5

本頁面說明 Bazel 的兩種瀏覽權限系統: 目標瀏覽權限負載瀏覽權限

這兩種可見度設定都能協助其他開發人員區分您的程式庫公開 API 和實作詳細資料,並在您的工作區擴大時協助強制執行結構。您也可以在淘汰公開 API 時使用可見性,允許現有使用者使用,但拒絕新使用者。

目標瀏覽權限

目標瀏覽權限:控管哪些使用者可能取決於你的目標,也就是誰 在 deps 等屬性中使用目標標籤。

如果目標 A 和目標 B 位於同一個套件中,或是 A 授予 B 套件的可見度,A 就會對 B 顯示。因此,套件是 精細程度,進一步決定是否允許存取如果 B 依附 A,但 A 無法向 B 顯示,則在分析期間,任何嘗試建構 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:mytargetvisibility 設為 [":__subpackages__", "//tests:__pkg__"],則任何目標都能使用此屬性 屬於 //some/package/... 來源樹狀結構的一部分,以及已定義的目標 在 //tests/BUILD 中,但不受 //tests/integration/BUILD 中定義的目標影響。

最佳做法:如要讓多個目標顯示相同的套件組合,請使用 package_group,而不要在每個目標的 visibility 屬性中重複列出清單。這麼做可提高可讀性,並避免清單不同步。

規則目標瀏覽權限

規則目標的瀏覽權限如下:

  1. visibility 屬性的值 (如有設定)。或其他

  2. 目標 BUILD 檔案中 package 陳述式的 default_visibility 引數值 (如果有此宣告);否則

  3. //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 的值:

  • 如果已設定旗標,則瀏覽權限為「私人」。

  • 否則會套用舊版行為:瀏覽權限與 BUILD 檔案的 default_visibility 相同,如果未指定預設瀏覽權限,則為私人。

請避免依賴舊版行為。來源檔案目標需要非私密的瀏覽權限時,請一律撰寫 exports_files 宣告。

最佳做法:盡可能公開規則目標,而非來源檔案。舉例來說,與其在 .java 檔案中呼叫 exports_files, 將檔案包裝在非私人 java_library 目標中。一般來說,規則目標應只直接參照位於同一個套件中的來源檔案。

範例

檔案 //frobber/data/BUILD

exports_files(["readme.txt"])

檔案 //frobber/bin/BUILD

cc_binary(
  name = "my-program",
  data = ["//frobber/data:readme.txt"],
)

設定設定的瀏覽權限

以往,Bazel 並未強制執行 select() 鍵中參照的 config_setting 目標的顯示設定。有 有兩個標記,可用來移除這個舊版行為:

  • --incompatible_enforce_config_setting_visibility 啟用瀏覽權限檢查這些目標為協助進行遷移 也會導致任何未指定 visibilityconfig_setting 會視為公開 (無論套件層級 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 屬性。一律會公開顯示。

隱含依附元件的瀏覽權限

部分規則具有隱含依附元件: 未寫到 BUILD 檔案中,但對應的依附元件 套用該規則的每個例項舉例來說,cc_library 規則可能會建立 隱含依附性從其個別規則目標到可執行的目標 代表 C++ 編譯器

目前,為了方便查看,這些隱含的依附元件會視為其他依附元件。也就是說,每個規則的例項都必須能看到所依附的目標 (例如 C++ 編譯器)。實際操作 通常意味著目標必須具有公開的瀏覽權限。

如要變更這項行為,請設定 --incompatible_visibility_private_attributes_at_definition。啟用後,問題中的目標只需對宣告為隱含依附元件的規則可見。也就是說,只有包含 .bzl 的套件可以查看此項目 檔案。在本範例中,C++ 編譯器可以是 就能避免系統 cc_library 規則。

載入瀏覽權限

載入可見度可控制是否可從其他 BUILD.bzl 檔案載入 .bzl 檔案。

以相同方式保護封裝的原始碼 負載瀏覽權限可保護由 .bzl 封裝的建構邏輯 檔案。舉例來說,BUILD 檔案作者可能會將部分重複的目標定義納入 .bzl 檔案中的巨集。沒有負載防護 瀏覽權限時,他們可能會發現其他協作者在 以防修改巨集造成其他團隊建構應用程式

請注意,.bzl 檔案不一定有對應的來源檔案目標。 如果是這樣,則無法保證載入可見度和目標可見度會一致。也就是說,同一個 BUILD 檔案或許也能載入 .bzl 檔案,但並未列在 filegroupsrcs 中, 反之亦然這有時會導致規則無法使用 .bzl 檔案做為來源碼,例如無法產生文件或進行測試。

進行原型設計時,您可以透過 --check_bzl_visibility=false。和 --check_visibility=false 一樣,這個項目應該 未完成的標記作業

自 Bazel 6.0 起才能使用載入瀏覽權限。

宣告負載瀏覽權限

如要設定 .bzl 檔案的載入瀏覽權限,請呼叫 檔案中的 visibility() 函式。 visibility() 的引數是套件規範清單,就像 package_grouppackages 屬性一樣。不過,visibility() 不接受排除套件 規格。

每個檔案只能在頂層 (非函式內) 呼叫 visibility() 一次,且最好緊接在 load() 陳述式之後。

與目標瀏覽權限不同,預設的載入瀏覽權限一律為公開。檔案 凡是未呼叫 visibility() 的項目,一律可從 工作區建議您在任何新 .bzl 檔案的頂端新增 visibility("private"),除非該檔案是專門用於套件外部。

範例

# //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 如何透過其 includes 屬性納入其他 package_group 相似。

假設您要淘汰廣泛使用的巨集。您希望只有現有使用者和您團隊擁有的套件可以查看。您可以這樣寫:

# //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 檔案,其中兩種宣告可能都是指 基礎架構以上述「計算可見度」一節的範例為基礎,您可以寫下:

# //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

bzl-visibility 建構工具 Lint

當使用者從名為 internalprivate 的目錄載入檔案時,如果使用者的檔案本身並未位於該目錄的父項下方,系統就會提供警告的Buildifier lint。這項 Lint 會在載入可見度功能之前執行,因此在 .bzl 檔案宣告可見度的工作區中,這項 Lint 就沒有必要。