深入了解 Zig 建置系統重構:速度、序列化與編譯器演進

Zig 程式語言持續在推動系統程式設計的邊界,不僅是在程式碼如何執行,還包括如何建置。Zig 建置系統最近的一次重大架構轉變,標誌著從單體式建置流程向解耦、序列化工作流的轉型。這項改變旨在解決一個日益嚴重的問題:隨著建置系統增加了更多功能——例如 --watch--fuzz--webui——建置邏輯本身的編譯開銷開始影響開發者體驗。

架構:配置器 (Configurer) 與 製造器 (Maker)

先前,build.zig 檔案與建置系統實作在 Debug 模式下會被編譯成一個單一且臃腫的程序。一旦 build.zig 邏輯在記憶體中完成建置圖 (build graph) 的建構,"build runner" 就會執行它。這意味著開發者每次執行 zig build 時,整個建置系統都必須經過處理。

為了消除這個瓶頸,Zig 引入了配置器 (configurer)製造器 (maker) 之間的分離:

  1. 配置器 (The Configurer): build.zig 檔案現在會在 debug 模式下被編譯成一個輕量級的小型程序。這個程序的唯一任務是在記憶體中建構建置圖,然後將其序列化為一個二進位配置檔案。
  2. 製造器 (The Maker): 當配置器在工作時,父程序 zig build 會非同步地在 Release 模式下編譯 "maker" 程序。maker 是實際執行建置圖的引擎。

由於 maker 程序只需要針對每個 Zig 版本編譯一次(歸功於全域快取),它本質上是一個靜態且經過優化的二進位檔,會讀取由配置器產生的序列化配置檔案。

效能影響

這種解耦提供了三個主要的效能優勢:

  • 減少編譯開銷: 每次變更時,只有使用者的 build.zig 邏輯會被編譯,而不是整個建置系統。
  • 智慧跳過: 如果建置系統發現沒有任何變更(例如,添加了像 -freference-trace 這樣的標記),它可以完全跳過 build.zig 邏輯並重複使用快取的二進位配置檔案。
  • 優化的執行: 執行建置圖的程序(maker)現在是以啟用完整優化的方式進行編譯的。

為了說明影響,Zig 團隊分享了 zig build -h 的基準測試結果。牆鐘時間 (wall time) 從 150ms 降至 14.3ms,代表執行時間減少了 90.4%。CPU 週期與指令數也呈現了類似的劇烈下降(超過 95%)。

重大變更與工具鏈

雖然這次重構在 API 角度上很大程度上是非破壞性的,但有一個顯著的變更會影響建置腳本如何處理參數。先前觀察 b.args 的方法已被取代:

舊方法:

if (b.args) |args| {
    run_cmd.addArgs(args);
}

新方法:

run_cmd.addPassthruArgs();

透過移除建置腳本直接觀察這些參數的能力,Zig 確保了更改參數不需要重新從原始碼重建建置腳本,進一步加速了開發循環。

除了效能之外,這項改變也使第三方工具受益。像 ZLS (Zig Language Server) 這樣的工具現在可以直接讀取序列化配置檔案,而不需要維護建置 runner 的複雜分支。

2026 年更廣泛的編譯器演進

建置系統的重構是 Zig 生態系統在整個 2026 年間進行優化與精煉的大趨勢的一部分。其他幾個關鍵更新突顯了該專案的方向:

增量編譯與型別解析

Zig 為 LLVM 後端引入了增量編譯,這顯著減少了在回報錯誤時花費在編譯器程式碼上的時間。此外,對內部型別解析邏輯的大規模重新設計(一個 30,000 行的 PR)使編譯器變得更加 "lazy"(懶惰)。它不再分析從未被初始化的型別欄位,這使得型別可以兼作命名空間,而不會觸發不必要的編譯錯誤。

I/O 與 "承諾之地" (Promised Land)

Zig 正朝著一個 I/O 實作可以被毫不費力地更換的未來邁進。std.Io.Evented 的引入允許開發者在執行緒 (threaded) I/O 與事件驅動 (event-driven) I/O(在 Linux 上使用 io_uring 或在 macOS 上使用 Grand Central Dispatch)之間切換,而無需更改核心應用程式邏輯。這是透過使用者空間堆疊切換(fibers/green threads)來實現的。

Windows 原生 API 偏好

為了減少臃腫並提高可靠性,Zig 的標準函式庫政策正轉向偏好使用原生 NT API,而非 Win32 (kernel32.dll) 封裝。透過繞過這些封裝,Zig 避免了不必要的堆積 (heap) 配置與未記錄的失敗模式,特別是在熵值生成 (entropy generation) 與檔案 I/O 方面。

社群觀點

社群對這些變化的反應很大程度上是正面的,使用者讚揚該語言的 "tinker-friendly"(適合動手嘗試)特性。一位使用者指出,Zig 感覺像是那些想要簡單、易於在休息後重新上手、且具備現代工具鏈的人們的 "sweet spot"(理想平衡點)。然而,也有部分使用者對語言目前的穩定性表示擔憂,提到像 async I/O 這樣的大型功能中頻繁的破壞性變更,認為在轉向穩定的生產環境版本之前應保持謹慎。

隨著 Zig 朝著 0.17.0 版本邁進,這些架構轉變顯示出一種語言正變得越來越自給自足——在減少對 C 與第三方 DLL 的依賴同時,也優化了用來建置它的工具本身。

Sources