GN 根目標

Fuchsia 版本使用 GN 的全新 root_patterns 功能,大幅降低 GN 和 Ninja 建構圖表的大小。這可大幅縮短 gn gen 時間並加快 Ninja 啟動時間。

不過,這項功能變更剖析 BUILD.gn 檔案時,GN 的預設行為可能令人意外。本文件將為您說明相關做法。

GN 預設行為

基於歷史因素,當在預設工具鍊的情境中評估後者時,GN 會將 BUILD.gn 檔案中定義的每個目標執行個體化,即使沒有仰賴這些目標也一樣。

舉例來說,假設以下三個 BUILD.gn 檔案定義了兩個目標,且兩者之間有一些依附元件:

 _//BUILD.gn____    _//foo/BUILD.gn__    _//bar/BUILD.gn_
|               |  |                 |  |                |
|   A           |  |         D -------------> E          |
|               |  |                 |  |                |
|      B --------------> C           |  |         F      |
|_______________|  |_________________|  |________________|

GN 剖析這項建構計畫時會發生以下情況:

  • GN 會先載入 //BUILD.gn 並加以評估。由於它使用預設工具鍊,因此會為該檔案中的所有項目 (例如 //:A//:B) 建立目標。

  • GN 會遵循其剛建立目標的依附元件,因為 //:B 依附於 //foo:C,所以會先載入 //foo/BUILD.gn 並進行評估。

  • 由於它仍位於預設工具鍊中,因此也會將該檔案中的所有目標例項化,因此建立 //foo:C//foo:D (即使後者並非 //:A//:B 的依附元件)

  • 它會再次追蹤依附元件,並載入 //bar/BUILD.gn、評估其並建立此處定義的所有目標,因此 //bar:E//bar:F

這將使最終建構圖包含許多超出所需數量的目標 (假設其中一個假設 //BUILD.gn 代表圖表的根層級)。

root_patterns GN 網購週

如要變更這項預設行為,您可以在 .gn 檔案中設定 root_patterns,或使用 --root-pattern=<pattern> 指令列選項 (至少一次)。

這些項目定義了目標標籤模式清單,用來篩選在預設工具鍊中評估的 BUILD.gn 檔案中,要建立的非依附元件目標。

舉例來說,將 gn gen --root-pattern=//:* 搭配相同的建構計畫使用後,GN 的行為就會以下列方式變更:

  • GN 會先載入 //BUILD.gn 並進行評估。由於該項目位於預設工具鍊中,因此所建立的檔案中的任何目標皆符合模式 (//:* 實際上是指「//BUILD.gn 中的任何目標」)。因此,系統會像之前一樣建立 //:A//:B

  • GN 會依循依附元件,然後載入 //foo/BUILD.gn 並評估其。它會建立 //foo:C,因為這是先前所建立其中一個目標的直接依附元件。但是,它「不會」建立 //foo:D,因為其標籤與 //:* 模式不符。

  • GN 並未建立 //foo:D,因此停止此處,因此不會載入 //bar:BUILD.gn

因此,GN 會建立 3 個目標,而非最終建構圖中的 6 個。

實際成效

在實務上,使用這項功能會大幅減少 GN 建構圖表的大小,同時加快 gn gen 的時間。例如,使用 fx set minimal.x64 設定:

                        Default     --root-pattern=//:*    Reduction

Target count             183761              48375          -73%
Ninja files size (MiB)    571.7              180.2          -68%
`fx set` peak RAM (GiB)    5.02               2.89          -42%
`gn gen` time (s)          14.9               6.15          -58%
`fx set` time (s)          16.0               6.77          -57%

//:root_targets 目標。

//BUILD.gn 檔案現在會定義名為 root_targets 的頂層目標,可用於將依附元件新增至建構圖中絕對必須含有的依附元件 (即使沒有其他依附項目也是如此)。

這對少數情況來說非常重要:

  • 某些特殊 generated_file() 目標,其輸出會做為其他目標的隱含輸入使用,但無法直接依賴,例如 //build/bazel:legacy_ninja_build_outputs

  • 幾個硬式編碼基礎架構工具的目標,預期必定會在樹狀結構中建構。

  • 某些建構工具設定預期的目標並未在 universe_package_labels 中列出,並只是假設其存在,這是因為同一個 BUILD.gn 檔案中定義的其他必要目標。

加入這份清單時應該最小化。如果您真的需要在最終 Ninja 建構資訊清單中定義特定內容,最好盡可能從任何其他頂層 //BUILD.gn 目標尋找實際的轉換依附元件。