Bazel 建構作業輸出內容

Bazel 使用嚴謹的配置來儲存 以免造成開發人員混淆本頁面嘗試清楚說明 有些事情能做得到

Bazel output_base

在設計上,bazel build 指令一律不會將檔案寫入專案來源。 目錄 (或其子目錄)。而 Bazel 使用特定使用者專屬 parallel 目錄,用來儲存名為 user_output_root 的所有輸出內容。 的預設值:

  • Linux 上的 ~/.cache/bazel/_bazel_$USER
  • %HOME%\_bazel_%USERNAME% (Windows)。

每個執行 bazel 的工作區目錄,都有一個獨立的目錄,名稱為 output_base 會在 user_output_root 下建立,如下所示:

  ${user_output_root}/<WORKSPACE_HASH>`

其中 <WORKSPACE_HASH> 是一長十六進位雜湊 (從 目錄的絕對路徑)。

由於這個路徑是完全無法預測的 bazel info output_base 會在 Bazel 專案中使用時進行列印。 例如:

$ mkdir -p /tmp/project1 && cd /tmp/project1 && touch WORKSPACE.bazel
$ bazel info output_base
Starting local Bazel server and connecting to it...
/usr/local/google/home/digit/.cache/bazel/_bazel_digit/6c7b78994da78136b5cb6b7607361ad3

$ mkdir -p /tmp/project2 && cd /tmp/project2 && touch WORKSPACE.bazel
$ bazel info output_base
Starting local Bazel server and connecting to it...
/usr/local/google/home/digit/.cache/bazel/_bazel_digit/c37b9d68308ee5abe2f781dd38b733b9

$ mkdir -p /tmp/not-a-project && cd /tmp/not-a-project
$ bazel info output_base
WARNING: Invoking Bazel in batch mode since it is not invoked from within a workspace (below a directory having a WORKSPACE file).
ERROR: The 'info' command is only supported from within a workspace (below a directory having a WORKSPACE file).
See documentation at https://bazel.build/concepts/build-ref#workspace

這個配置很有彈性,但不盡完美:

  • Pro:同一部機器上的多位使用者可以共用相同的唯讀權限 專案目錄

  • Pro:同一位使用者一律會使用多個專案目錄 獨立的輸出路徑

  • Con:直接透過指令列查看產生的檔案 圖形探索工具非常困難。

  • Con:移除專案目錄 (例如使用 rm -rf .../my-project) 不會移除輸出的內容 (這是重要的廢棄物來源)。

  • Con:移動專案目錄 (例如透過 mv my-project my-project2) 不會重複使用先前的 output_base 內容 (並保留舊內容) 目前無法存取)。

  • Conuser_output_root 的預設位置,因此 output_base 通常不位於相同的檔案系統 / 分區上 專案。這可能會對效能 / 磁碟造成非預期的結果 。

呼叫 bazel clean 即可從目前的 output_base 移除建構輸出內容。 這項操作必須完成,才能移除來源專案目錄。

實務上,您可以輕鬆使用以下程式碼建構 user_output_root 的內容: 建構出從未經過適當清理的過時 Bazel 專案成果。 更糟的是,手動移除 user_output_root 可能無法運作。 因為 Bazel 預設會建立唯讀建構構件 例如 rm -rf ~/.cache/bazel 執行指令!

Bazel output_base 內容:

許多內容實際上都儲存在 output_base 底下:

  • 外部存放區的 Workspace 目錄

    這些項目對應外部專案依附元件。這類項目通常不屬於 專案來源樹狀結構,但從網路下載或產生 編寫程式

    他們的內容會儲存在「${output_base}/external/<repository_name>」底下, 其中 external 部分是硬式編碼,而 <repository_name> 則符合 外部存放區的正規名稱

  • 版本構件

    執行 bazel build 產生的檔案。這些資料會儲存在以下位置:

    ${output_base}/execroot/<workspace_name>/bazel-out/<config_dir>/bin/
    

    地點:

    • execrootbazel-outbin 部分為硬式編碼,因此無法使用 已變更。

    • 針對專案專屬 BUILD.bazel 檔案中定義的目標, <workspace_name> 預設為 __main__,除非在專案的 WORKSPACE.bazel 檔案,其中包含類似下方的指令:

      workspace(
        name = "my_project",
      )
      ```
    
    - For targets defined in external repositories, `<workspace_name>` matches
    the repository's canonical name.
    
    - The `<config_dir>` value is a name derived from the build configuration used
    to configure the target that generated the build artifact. This allows
    rebuilding the same target in different ways, each time using a different
    `<config_dir>` value.
    
    Note: The `<config_dir>` value is **generally unpredictable**. More on this [here][bazel-config-dirs]
    
  • 測試結果

    呼叫 bazel test 時產生的記錄檔,儲存在下方 ${output_base}/execroot/<workspace_name>/bazel-out/<config_dir>/testlogs/

  • 內部快取和設定檔

    可供遠端建構作業和遠端快取功能使用。您可以按照 開發人員。

Bazel execroot 目錄:

execroot 可用來執行可產生建構構件的 Bazel 指令。 其運作方式取決於是否為特定動作啟用沙箱機制。

  • 在 Linux 上,所有動作都會預設啟用沙箱機制。 Windows 不提供沙箱支援 (自 Bazel 7 起)。

  • Bazel 動作可以明確使用 「no-sandbox」標記的定義。

  • 您可以採用下列選項,全面停用沙箱機制: 叫用 bazel 時為 --spawn_strategy=local

不使用沙箱機制:

停用沙箱機制時,所有會產生構件的建構動作 在特定工作區中 ${output_base}/execroot/<workspace_name>

動作的 就會使用這個詞彙

Bazel 可確保該指令使用的輸入來源產生符號連結, 。

舉例來說,會編譯 //src/foo/foo.cc 檔案的動作 其中包含 #include "foo.h",對應 //src/foo/foo.h 可以 如下所示:

gcc -c -o bazel-out/k8-fastbuild/bin/src/foo/foo.o src/foo/foo.cc -Isrc/foo

這麼做的原因:

  • 在執行指令之前,Bazel 會建立符號連結 ${output_base}/execroot/__main__/src 指向 $PROJECT/src, 如此一來,src/foo/foo.ccsrc/foo/foo.h 就會解析為 預期有 $PROJECT/src/foo/foo.cc$PROJECT/src/foo/foo.h

  • bazel-out/k8-fastbuild/bin/src/foo/foo.o 位置是最終結果 將 foo.cc 建立 Deployment 設定

採用沙箱機制:

啟用沙箱機制時,Bazel 會為每個指令建立 目錄 (例如 ${output_base}/sandbox/linux-sandbox/<random-number>) 會建立符號連結樹狀結構來模仿其下方的 execroot 版面配置 只會對已知的輸入值產生影響在此情況下,如下所示:

  • 輸入來源的符號連結 ${sandbox}/execroot/__main__/src/foo/foo.cc${sandbox}/execroot/__main__/src/foo/foo.h 指向 $PROJECT/src/foo/foo.cc$PROJECT/src/foo/foo.h

  • ${sandbox}/execroot/__main__ 下執行完全相同的指令。 而不是 ${output_base}/execroot/__main__

  • 指令完成後,請複製位於 的沙箱路徑中已知的輸出內容 ${sandbox}/execroot/__main__/bazel-out/k8-fastbuild/bin/src/foo/foo.o 最終位置 ${output_base}/execroot/__main__/bazel-out/k8-fastbuild/bin/src/foo/foo.o

  • 最後,沙箱目錄,以及其中所有的內容都會遭到移除。這也 表示系統會忽略未宣告的輸出內容。