顯示設定

回報問題 查看原始碼 。 。 。 。 夜間。 。 7.3 。 。 7.2 。 。 7.17.0 。 。 6.5

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

這兩種瀏覽權限都能幫助其他開發人員區分 程式庫的公用 API 及其實作詳細資料,有助於強制執行結構 。淘汰公開的資料庫時 API,允許現有使用者同時拒絕新使用者。

目標瀏覽權限

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

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

最佳做法:讓多個目標顯示同一個組合 ,請使用 package_group,而不要在每個套件中重複列出清單 目標的 visibility 屬性。這樣可以提高可讀性,防止 列出無法同步的多個清單

規則目標瀏覽權限

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

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

  2. 如果 default_visibility敬上 package 陳述式的引數 目標的 BUILD 檔案 (如果這類宣告存在);或其他

  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 並未針對以下項目強制執行瀏覽權限: config_setting 個目標: select() 的鍵所參照。有 有兩個標記,可用來移除這個舊版行為:

  • --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++ 編譯器

系統會根據 套件,內含定義規則 (或切面) 的 .bzl 檔案。於 如範例所示,只要 C++ 編譯器位於 做為 cc_library 規則的定義。如果 定義中不會顯示隱含依附元件,系統會使用以下條件進行檢查 參照 cc_library 目標。

如要變更這項行為,請停用 --incompatible_visibility_private_attributes_at_definition。 停用後,系統會將隱含依附元件視為任何其他依附元件。 這表示,相依的目標 (例如 C++ 編譯器) 必須 所有執行個體都能看到這個狀態在實務上,這通常代表 必須公開顯示

如要限制特定套件的使用規則,請使用 載入瀏覽權限

載入瀏覽權限

載入瀏覽權限控管 .bzl 檔案能否從其他來源載入 目前套件之外的 BUILD.bzl 檔案。

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

請注意,.bzl 檔案不一定有對應的來源檔案目標。 如果確實如此,則無法保證載入可視性和目標 顯示設定也就是說,同一個 BUILD 檔案或許也能載入 .bzl 檔案,但並未列在 filegroupsrcs 中, 反之亦然這有時可能會導致想使用的規則發生問題 .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 檔案,其中兩種宣告可能都是指 基礎架構以因素顯示瀏覽權限範例為基礎 就可以寫成:

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

建構工具 Lint 當使用者從名為 internal 的目錄載入檔案時,系統會提供警告訊息 或 private (使用者檔案本身並非位於該父項的父項之下) 目錄。此 Lint 會早於載入能見度功能,因此不需要 為 .bzl 檔案宣告瀏覽權限的工作區。