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
目標尋找實際的轉換依附元件。