使用外部依附元件

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

Bazel 可以依賴其他專案的目標。彼此的依附元件 稱為外部依附元件

憑證中的 WORKSPACE 檔案 (或 WORKSPACE.bazel 檔案) 工作區目錄 告知 Bazel 如何取得其他專案資料來源這些其他專案 包含一或多個 BUILD 檔案,且有各自的目標。以下資料夾中有 BUILD 個檔案 主要專案可以依附於這些外部目標 WORKSPACE 檔案。

舉例來說,假設系統中有兩個專案:

/
  home/
    user/
      project1/
        WORKSPACE
        BUILD
        srcs/
          ...
      project2/
        WORKSPACE
        BUILD
        my-libs/

如果 project1 需要使用目標 :foo/home/user/project2/BUILD,它可以指定名為 在 /home/user/project2 找到 project2。然後指定 /home/user/project1/BUILD 可能依附於 @project2//:foo

WORKSPACE 檔案可讓使用者依附於 或是從網際網路下載的檔案使用的語法與 BUILD 相同 但是允許另一組稱為「存放區規則」的規則 (有時 也稱為 工作區規則)。Bazel 提供了幾個內建存放區 規則以及一組嵌入式 Starlark 存放區 規則。使用者也可以編寫自訂存放區 規則,即可進行更複雜的行為。

支援的外部依附元件類型

可使用的外部依附元件分為幾種基本類型:

依附於其他 Bazel 專案

如要使用第二個 Bazel 專案中的目標 使用 local_repositorygit_repository。 或 http_archive 建立符號連結、參照 Git 存放區或下載 可以分別使用

舉例來說,假設您正在處理 my-project/ 專案 需要使用您在同事專案 coworkers-project/ 中的目標。兩者皆有 專案使用 Bazel,因此您可以將同事的專案新增為 然後使用同事自行定義的目標 BUILD 檔案。請將以下內容新增到 my_project/WORKSPACE

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

如果同事指定的是//foo:bar,則可將專案稱為 @coworkers_project//foo:bar。外部專案名稱必須是 有效的工作區名稱

取決於非 Bazel 專案

前置字串為 new_ 的規則,例如 new_local_repository, 可讓您在不使用 Bazel 的專案中建立目標

舉例來說,假設您正在處理 my-project/ 專案 要使用的專案:coworkers-project/。您同事的 專案使用 make 進行建構,但您想依附其中一個 .so 檔案 所產生的費用若要這樣做,請在 my_project/WORKSPACE 中新增以下內容:

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file 會指定要疊加在現有專案上的 BUILD 檔案, 範例:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

接著,您可以從專案內依附 @coworkers_project//:some-lib BUILD 個檔案。

視外部套件而定

Maven 構件和存放區

使用規則集 rules_jvm_external 從 Maven 存放區下載構件,並以 Java 格式提供構件 依附元件

擷取依附元件

根據預設,系統會在 bazel build 期間視需要擷取外部依附元件。如果 如要預先擷取一組特定目標所需的依附元件,請使用 bazel fetch。 如要無條件擷取所有外部依附元件,請使用 bazel sync。 擷取的存放區會儲存在輸出基準中, 在每個工作區中發生一次

覆蓋依附元件

建議您盡可能在 專案。您必須對依附元件進行編譯,最後才能編譯依附元件 作為最終二進位數字。但如果不這樣做 影子依附元件請參考下列情境:

我的專案/工作區

workspace(name = "myproject")

local_repository(
    name = "A",
    path = "../A",
)
local_repository(
    name = "B",
    path = "../B",
)

空調

workspace(name = "A")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "...",
)

B/工作區

workspace(name = "B")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)

AB 都依附於 testrunner,但兩者相依 不同的 testrunner 版本這些測試執行工具沒有理由 不平靜在 myproject 內共存,但是它們會與 因為兩者的名稱相同如要宣告這兩個依附元件 更新 myproject/WORKSPACE:

workspace(name = "myproject")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "testrunner-v1",
    urls = ["https://github.com/testrunner/v1.zip"],
    sha256 = "..."
)
http_archive(
    name = "testrunner-v2",
    urls = ["https://github.com/testrunner/v2.zip"],
    sha256 = "..."
)
local_repository(
    name = "A",
    path = "../A",
    repo_mapping = {"@testrunner" : "@testrunner-v1"}
)
local_repository(
    name = "B",
    path = "../B",
    repo_mapping = {"@testrunner" : "@testrunner-v2"}
)

這個機制也可用來加入鑽石。例如 AB 具有相同依附元件,但用不同的名稱呼叫,這些依附元件 加入 myproject/WORKSPACE 中

透過指令列覆寫存放區

如要透過指令列使用本機存放區覆寫宣告的存放區, 請使用 --override_repository敬上 旗標。使用此旗標時,系統會變更外部存放區的內容 並變更原始碼

舉例來說,如要將 @foo 覆寫為本機目錄 /path/to/local/foo, 傳遞 --override_repository=foo=/path/to/local/foo 標記。

以下列舉幾個用途:

  • 偵錯。舉例來說,您可以覆寫 http_archive 存放區 到本機目錄,方便您進行變更
  • 供應商。如果您所在的環境無法進行網路呼叫, 覆寫以網路為基礎的存放區規則,指向本機目錄 。

使用 Proxy

Bazel 會從 HTTPS_PROXYHTTP_PROXY 挑選 Proxy 位址 環境變數,並使用這些環境變數來下載 HTTP/HTTPS 檔案 (如有指定)。

支援 IPv6

在僅支援 IPv6 的機器上,Bazel 可以用 沒有變更不過,在雙重堆疊 IPv4/IPv6 機器上,Bazel 會採用相同的 都採用 Java 的慣例:如果啟用 IPv4,系統會優先使用 IPv4。在某些情況下 例如:IPv4 網路無法解析/連線至外部位址時 這可能會導致 Network unreachable 例外狀況並建構失敗。 在這種情況下,您可以覆寫 Bazel 的行為,優先使用 IPv6 使用 java.net.preferIPv6Addresses=true 系統資源。 詳細說明:

  • 使用「--host_jvm_args=-Djava.net.preferIPv6Addresses=true啟動選項 例如,在 .bazelrc 檔案

    startup --host_jvm_args=-Djava.net.preferIPv6Addresses=true

  • 如果您執行的 Java 建構目標需要連上網際網路 (整合測試有時需要) --jvmopt=-Djava.net.preferIPv6Addresses=true 工具旗標,例如 .bazelrc 的下一行:

    build --jvmopt=-Djava.net.preferIPv6Addresses

  • 如果使用 rules_jvm_external, 舉例來說,如需依附元件版本解析,請將 -Djava.net.preferIPv6Addresses=trueCOURSIER_OPTS 環境變數,為 Coursier 提供 JVM 選項

遞移依附元件

Bazel 只會讀取 WORKSPACE 檔案中列出的依附元件。如果您的專案 (A) 依附於另一個專案 (B),該專案列出三個依附元件 專案 (C),請在其 WORKSPACE 檔案中新增兩個 B 並將 C 加入專案的 WORKSPACE 檔案這項規定可能會使 WORKSPACE 的檔案,但會限制只有一個程式庫的機率 包括版本 1.0 的 C,另一個版本則包含 C 2.0 版。

快取外部依附元件

根據預設,Bazel 只會在符合以下條件的情況下重新下載外部依附元件 定義變更定義中參照的檔案 (例如修補程式) 或 BUILD 檔案) 也會將 bazel 納入考量。

如要強制重新下載,請使用 bazel sync

版面配置

外部依附元件全部下載至子目錄下的目錄 輸出基準中的 external。如果 本機存放區,系統會建立符號連結 不必建立新目錄 您可以執行下列指令來查看 external 目錄:

ls $(bazel info output_base)/external

請注意,執行 bazel clean 並不會刪除外部外部 IP 位址 目錄。如要移除所有外部構件,請使用 bazel clean --expunge

離線版本

有時候是理想或需要離線執行建構。適用對象 像是搭乘飛機 prefetching所需的資料 含有 bazel fetchbazel sync 的存放區就足夠了;另外, 使用 --nofetch 選項,可停用擷取其他存放區的功能 建構期間

如果是真正的離線版本,就必須提供必要檔案 一個與 bazel 不同的實體,bazel 可以支援 --distdir。每當存放區規則要求 bazel 透過以下方式擷取檔案時 ctx.downloadctx.download_and_extract。 並提供檔案的雜湊總和 bazel 會先查看該選項指定的目錄 符合第一個網址基準名稱的檔案,然後使用該本機副本 (如果雜湊相符)。

Bazel 本身會使用這項技術,從發行 Artifact。 方法在於收集所有需要的外部 依附元件 在內部 distdir_tar

然而,bazel 允許在存放區規則中執行任意指令。 而無從得知他們是否呼叫網路因此 bazel 無法選擇 強制將建構作業完全離線因此,測試建構能正常運作 離線需要進行外部封鎖 如同 bazel 所在 啟動測試。

最佳做法

存放區規則

存放區規則通常應負責:

  • 偵測系統設定並寫入檔案。
  • 尋找系統上的其他位置資源。
  • 從網址下載資源。
  • 將 BUILD 檔案產生或符號連結到外部存放區目錄中。

請盡量避免使用 repository_ctx.execute。例如,使用非 Bazel C++ 時 如果程式庫使用 Make 建構,建議使用 repository_ctx.download(),然後 撰寫會建立該檔案的 BUILD 檔案,而不是執行 ctx.execute(["make"])

偏好 http_archive 使用 git_repository,以及 new_git_repository。原因如下:

  • Git 存放區規則依附於系統 git(1),HTTP 下載工具則是建立 且沒有系統依附元件。
  • http_archive 支援 urls 清單做為鏡像,而 git_repository 僅支援 單一 remote
  • http_archive 可使用存放區快取,但不支援 git_repository。詳情請見 #5116

不要使用 bind()。請參閱「考慮移除 bind」長時間 討論其問題和替代方案。