博客 / 詳情

返回

FrankenPHP 原生支持 Windows 了

FrankenPHP 原生支持 Windows 了

FrankenPHP 是什麼

FrankenPHP 是一個基於 Caddy 和 PHP 構建的現代 PHP 應用服務器,目標是簡化 PHP 應用的運行與部署。它既可以作為傳統 PHP 應用的運行環境,也提供了 Worker Mode、Hot Reloading 等更偏現代化的能力,因此這兩年在 PHP 社區裏關注度一直不低。

FrankenPHP 現已正式提供官方 Windows 支持,並立即可用。

自項目發佈以來,Windows 原生支持一直是 FrankenPHP 社區呼聲最高的需求之一。現在,這項能力已經正式落地。也就是説,FrankenPHP 已經可以在 Windows 上原生運行,並實現 100% 兼容,包括 Worker Mode、Hot Reloading 等核心特性。

性能表現

這次支持並不只是“能用”,性能表現也相當可觀。社區已經給出了一些早期基準測試結果。

有用户在同一台 Windows Server 2022 機器上,將 FrankenPHP 與一個已經過優化的 Nginx/PHP-FPM 環境進行了對比。結果很直接:僅僅切換服務器運行時,就獲得了 3.6 倍性能提升,增幅超過 260%

此外,@henderkes 提供的一組更完整的基準測試,也進一步驗證了 FrankenPHP 在 Windows 原生環境下、不同工作負載中的性能收益。

不過需要説明的是,原生 Windows 支持雖然已經足夠快,在開發環境以及很多生產負載下也足夠方便,但如果目標是追求更高的極限吞吐量,那麼通過 WSL 運行 FrankenPHP 仍然更有優勢,因為 Linux 在底層 I/O 和網絡架構上依舊更強。如果生產環境允許,優先選擇 Linux 仍然是更穩妥的方案。

難點:兩個編譯器體系的衝突

為什麼這件事花了這麼久?

實際上,此前已經有開發者嘗試把 FrankenPHP 移植到 Windows。但除了常見的跨平台問題,例如文件路徑和文件系統差異,更麻煩的是一個底層且結構性的兼容問題。

問題的核心可以概括為下面幾點:

  • FrankenPHP 是一個 Go 庫,它通過 CGO 調用 PHP 的 libphp
  • Windows 上的官方 PHP 構建使用 Visual Studio(MSVC)編譯,以保證性能和穩定性
  • 但 Go 的 CGO 在 Windows 上長期不支持 Visual Studio,而是隻支持 MinGW(GCC)
  • 這就留下了一個巨大的兼容性鴻溝:兩邊根本無法直接鏈接在一起

解決路徑

圍繞這個問題,項目曾嘗試過幾種方案,但最終都沒有走通。

方案一:讓 Windows 版 PHP 支持 GCC

第一種思路,是給 PHP 打補丁,讓 Windows 版 PHP 支持 GCC 編譯。但 PHP 維護者並不希望為此引入額外複雜度,這一點並不難理解。另一方面,項目本身也希望直接使用官方二進制,以保證穩定性並避免生態分裂。

因此,依賴 Visual Studio(MSVC)之外的其他編譯器並不可行。畢竟,MSVC 是 PHP 官方唯一支持的 Windows 編譯器。

方案二:“Frankenstein” 構建方案(llvm-mingw)

第二種思路是折中方案:使用 llvm-mingw 編譯 FrankenPHP,再把它鏈接到官方 Visual Studio 編譯的 PHP。

這個方案最終失敗,原因是 標準庫不匹配

當你把 MinGW 編譯出來的二進制(使用 msvcrt.dll 或自己的運行時)與 MSVC 編譯出來的二進制(使用 ucrt / vcruntime)混在一起時,就會遇到嚴重問題。比如一側分配內存(malloc),另一側去釋放;或者嘗試跨邊界傳遞文件描述符,程序都會直接崩潰。

本質上,它們説的是兩種不同方言的 “C”。

突破點:Go 1.26 與 clang

最終,項目找到了更合理的路徑:為 CGO 增加對 Visual Studio 提供的 Clang/LLVM 前端的支持。

可以簡單理解為,Visual Studio 自帶一套 Clang,它可以作為 MSVC 編譯器(cl.exe)的替代實現來工作。它接受 CGO 更適配的 GCC 風格參數,同時底層又使用微軟的 STL 和運行時庫。

也就是説,它結合了兩邊的優點。

在調研現有方案、準備給 Go 提交補丁的過程中,項目方還發現 Google 其實已經提交過一份非常關鍵、但幾乎沒有公開説明的實現,處理的正是這個問題。

這份補丁最終進入了 Go 1.26

藉助 Go 新增的這項能力,再配合 lld-link 鏈接器,我們終於能夠使用與 PHP 本身相同的工具鏈來編譯 FrankenPHP。

測試結果

最終的成果,是拿到了一個 原生 Windows 二進制,並且它直接鏈接到 PHP 官方提供的穩定版本二進制。

更關鍵的是,因為鏈接的是官方 PHP 構建,所以所有 Windows 上受支持的原生 PHP 擴展,在 FrankenPHP 中都能直接工作,無需額外適配。

在處理完 Windows 特有的一些細節後,FrankenPHP 代碼庫也完成了相應更新。目前可以確認:全部測試均已通過

  • ✅ 原生 Windows 二進制
  • ✅ 完整擴展支持
  • ✅ Worker Mode
  • ✅ Hot Reloading

致謝與贊助

這項複雜工作之所以能夠完成,要感謝 Intelligence X 和 Les-Tilleuls.coop 的慷慨贊助。

開源項目的可持續性並不容易。如果團隊或公司依賴 FrankenPHP、Caddy 或 API Platform,可以考慮通過 GitHub 提供贊助。類似支持,往往也是這類底層技術問題能夠持續推進的重要前提。

現在就可以使用

這項支持已經合併到 Pull Request #2119,最新版 Windows 二進制也已經可以從發佈頁直接下載。

原文最後也特別感謝了參與調研和實現的開發者,尤其是 @TenHian 在早期探索階段的工作,以及 @henderkes 在最終實現中投入的大量精力。

如果日常主要在 Windows 上開發 PHP,現在已經可以直接試用 FrankenPHP。
FrankenPHP 原生支持 Windows 了

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.