Fuchsia 建構系統:變化版本

Fuchsia GN 建構機器可讓您在不同的「變化版本」中建構不同的元件。變化版本通常只會使用額外的編譯器選項,但如果您編寫更多 GN 程式碼,就可以的功用不僅止於此。到目前為止定義的變體可提供消毒工具LTO 等功能。

指定變化版本

變化版本規格會使用 GN 建構引數 select_variant 傳入版本。請注意,這些變化版本選取器的順序相當重要,將在下文的語法一節中說明。

使用 fx set,傳遞具有 --variant= 標記的字串變數選取器:

fx set core.x64 --variant=asan/cat --variant=asan/ledger --variant=host_asan

這個範例會指示建構作業編譯「cat」和「帳本」的 Fuchsia 二進位檔,以及所有使用位址清理器的主機工具 (如需這些字串的確切語法,請參閱下文)。

如果您已有建構目錄,可直接編輯 GN 引數,即可新增或修改變化版本 (視需要替換 out/default 的建構 GN 輸出目錄):

fx gn args out/default

這個指令會開啟編輯器。請在該檔案中附加一行,將變化版本選取器做為字串清單指派給 select_variant 建構引數:

select_variant = [ "asan/cat", "asan/ledger", "host_asan" ]

選取器語法

一般來說,您會使用一組字串做為變化版本選取器。每個變化版本都會定義變化版本名稱,並視需要定義要套用的內容。系統會按照您指定的順序測試選取器,並套用第一個相符的項目。

  • 單獨使用變化版本名稱 (例如 asanhost_ubsan),將具名變化版本套用至全域。這些全域選取器應列在最後。

  • 使用 variant_name/target_output_name 等格式 (例如 asan-ubsan/ledgerhost_asan/zxdb_tests),將已命名的變化版本套用至特定目標。應列在全域選取器之前,以覆寫較一般規則。

系統會將變化版本與二進位檔 (例如 executableloadable_moduletestfuchsia_driver) 進行比對,而非 Fuchsia 套件、Fuchsia 元件、共用程式庫、靜態資料庫或來源集。當變化版本與目標相符後,其依附的所有程式庫都會以該變化版本進行編譯。由於 Fuchsia 套件和元件與選擇變化版本無關,因此在變化版本規格中指定套件或元件名稱不會產生任何作用。套件中的每個執行檔或模組都可以指定自己的變數。

根據預設,目標輸出名稱是指您提供給 GN 目標定義的名稱 (在引號中)。這個目標會定義 my_program 目標,您可以透過選取器 asan/my_program 將其套用為該目標:

executable("my_program") { ... }

部分目標會使用 GN output_name 變數覆寫輸出名稱 (通常為提供全域不重複的二進位檔名稱來避免衝突)。在此情況下,變化版本選取器會與已覆寫的輸出名稱相符,因此您仍可以使用 asan/my_program 套用 Asan 模式:

executable("bin") {
  output_name = "my_program"
}

在某些情況下,範本可能會以不明顯的方式覆寫輸出名稱。如果發現變化版本不相符,最簡單的方法就是在建構目錄中尋找二進位檔並使用該名稱。

進階選取器

您也可以將大括號括住的 GN「範圍」做為變化版本選取器,以完全掌控比對目標的建構方式。這些引數必須在「gn args」中設定,而非透過「fx set」指令列。詳情請參閱 select_variant 建構引數說明文件。

如要查看可用的變化版本清單,並進一步瞭解如何定義新的變數,請參閱 known_variants 建構引數。

常見的變化版本名稱

  • debug:未最佳化編譯。
  • release:最佳化編譯。
  • asanAddress Sanitizer 用於檢查記憶體的編譯時間檢查作業,例如「已釋放記憶體」和「超出限制的陣列存取」。
  • ubsan未定義行為清理工具,用於對未定義行為 (例如整數溢位和不正確的指標) 進行編譯時間檢查。
  • asan-ubsan:亞洲 + ubsan 的組合。
  • lto連結時間最佳化,用於整個程式最佳化。
  • thinlto精簡連結時間最佳化是更少量的程式最佳化,可加快編譯。
  • coverage:用於產生 C++ 程式碼涵蓋率資訊的檢測編譯。
  • coverage-rust:適用於 Rust 的涵蓋範圍。由於 LLVM 程式庫版本在 Rust 和 C++ 編譯器之間偏差,因此不能與 coverage 同時使用。
  • kasan:僅套用至核心。
  • gcc:使用 GCC 而非 Clang 編譯。這項功能僅支援啟動設定,且只會影響包括核心等特定目標。

使用消毒器在模糊化下執行測試時,系統會使用 asan-fuzzer 等模糊變化版本。這些變數並不適合手動選取,請改為按照模糊操作說明設定版本。

此外,還有一些精簡選取器會將變化版本套用至主機二進位檔 (在 Linux 或 Mac 主機電腦上執行的工具): * host_asan * host_asan-ubsan * host_coverage * host_coverage-rust * host_profile

某些預建版本可能不適用於所有變化版本。特別是 ffmpeg,請參閱 //src/media/lib/ffmpeg/BUILD.gn

疑難排解附註

檢查變化版本是否已套用至二進位檔

每個變化版本都有專屬的輸出目錄和工具鍊名稱,名為 <architecture>-<variant name>。在建構作業中,這些二進位檔會複製到根目錄建構目錄。舉例來說,指定 x64 裝置的 Asan-ubsan 變化版本會透過 //build/toolchain/fuchsia:x64-asan-ubsan 工具鍊進行編譯,然後將二進位檔放入 out/default/x64-asan-ubsan (將建構目錄替換成「default」)。

執行 GN 後 (通常是建構的第一個步驟) 會產生 binaries.json 檔案,其中包含每個二進位檔的資訊。您可以透過 dist 檔案名稱和 label (工具鍊名稱位於括號中) 判斷哪個變數是用來編譯二進位檔。如果二進位檔可能會在目標和主機上編譯,另請注意記錄中的 os 欄位。以下是使用「asan-ubsan」變體為 x64 編譯的 Fuchsia 二進位檔範例:

  {
    "cpu": "x64",
    "debug": "x64-asan-ubsan/exe.unstripped/blobfs",
    "dist": "x64-asan-ubsan/blobfs",
    "elf_build_id": "x64-asan-ubsan/blobfs.build-id.stamp",
    "label": "//src/storage/blobfs/bin:blobfs(//build/toolchain/fuchsia:x64-asan-ubsan)",
    "os": "fuchsia",
    "type": "executable"
  },

複製 ASan 失敗

我們的基礎架構會在啟用 ASan 的設定中執行測試。如要複製啟用 ASan 的基礎架構版本,請使用 fx repro <build_id> 並執行其產生的指令。

請注意,這項操作會建構由基礎架構執行的所有測試,並安裝在系統映像檔中。這並非您的理想原因,原因如下:

  • 建構所有測試通常速度緩慢且非必要。開發人員可以發現,將套件標籤限制在需要的測試內,是更有效的做法。
  • 提前安裝系統映像檔中的所有測試,表示軟體部署工作流程無法練習。

從已啟用 ASan 的二進位檔中啟動執行檔

如果您嘗試使用 ASan 變體,可能會遇到如下所示的錯誤:

launcher: error: Launch: elf_load: handle_interp failed
dlsvc: could not open 'asan/ld.so.1'

Fuchsia 是以套件和元件為建構基礎。每個元件都包含執行所需的所有共用程式庫。這有助於 Fuchsia 避免程式庫版本管理問題,避免造成其他作業系統的困擾。也就是說,如果您想從元件中執行二進位檔,則必須為該二進位檔提供適當的共用程式庫載入器。

在 Fuuchsia 安裝的 /boot/ 目錄中,有一組指令列程式,不包含在套件中,而是在啟動檔案系統中。這些程式沒有自己的共用程式庫載入器,因此會使用元件執行元件所提供的共用程式庫。這個做法通常有效,因為 shls 等程式有極少且非常常見的依附元件。然而,我們無法保證元件的套件擁有足夠或相容的共用程式庫,以滿足指令列程式的需求。啟用 ASan 的套件通常未包含這些程式適用的啟動器,因此啟用 ASan 的大多數元件無法透過 /boot 執行執行檔。如果已啟用 ASan 的元件嘗試這麼做,便會收到上方的錯誤。

幸運的是,修正作業確實涉及執行所有套件應執行的動作,也就是明確宣告其依附元件。如果套件依附於二進位檔,請將其宣告為依附元件,然後使用該宣告的依附元件,而不是 /boot 目錄中的依附元件。若是建構系統,//build/config/fuchsia/zircon_images.gni 中定義的 zircon_extras_manifest 規則可讓您依附於 /boot 目錄中的任何二進位檔。這些套件會安裝在 /pkg/bin/ 中,而您應該從該處執行。