Linux 二進位相容性的聖杯:musl 與 dlopen (★ 74 分)
在 Linux 上發行命令列工具或伺服器通常很容易:用 Go 直接編譯出單一靜態執行檔,就能在 kernel 3.2 以上的多數發行版上跑。然而一旦要用到硬體加速圖形,問題就變複雜了:GPU 驅動與圖形堆疊通常必須透過 C ABI(Application Binary Interface,應用程式二進位介面)去呼叫共享函式庫,而這些 C 函式庫往往綁定特定的 libc(C 標準函式庫),最常見是 glibc(GNU libc),但也有採用 musl(另一套 libc)的發行版;兩者編譯出的程式與函式庫彼此並不相容,導致「同一個 Linux 執行檔到處跑」在圖形情境下不再成立。作者改用 Void Linux 的 musl 版本後,也親身踩到像 Zed 編輯器與自身 graphics.gd 專案在 musl 上建置困難的坑,原因之一是 Go 對 musl 的 c-shared/c-archive 產物支援不完整。
為了讓 graphics.gd(把 Go 與 Godot 開源遊戲引擎結合的工具鏈)能在 musl 上正常建置,作者用 build-overlay 方式修補 Go runtime,並引入一個自訂的 `GOOS=musl` 目標,讓 musl 建置流程可行。接著他放棄在 musl 上做 c-shared(原本可直接「插」進官方 Godot 執行檔),改成把 Go 程式碼與 Godot 的 c-archive 直接連結,產出單一執行檔,達成 musl 版支援。但這也帶來發行上的尷尬:若要涵蓋所有 Linux 使用者,專案可能得同時提供 glibc 版與 musl 版,還要讓一般使用者理解差異並選對檔案,等於把相容性難題轉嫁給使用者。
作者接著把目標推到「單一靜態執行檔 + 圖形」:理論上 musl 對靜態連結更友善,Godot 在 Linux 也內建多數相依;但實作上 Godot 仍需要用 dlopen(POSIX 的動態載入介面,於執行期間載入 .so)去存取 X11/Wayland(Linux 顯示協定)、OpenGL/Vulkan(圖形 API)等,結果在 musl 的靜態執行檔上直接出現「Dynamic loading not supported」。musl 之所以拒絕在靜態情境實作 dlopen,核心理由是 TLS(thread-local storage,執行緒區域儲存)等機制與 glibc 有根本差異,混用可能導致難以預期的錯誤。作者利用 dlopen 以 weak symbol(弱符號)形式連結的特性,改以自行實作 dlopen:參考 detour 與 Cosmopolitan libc 的作法,在同一行程中載入並執行一段小型 C 輔助程式,把宿主系統的動態連結器「帶進來」,借用系統的 dlopen,並用彙編 trampoline(跳板)在呼叫期間切換到系統 libc 的 TLS,再跳回主程式,效果有點像 cgo(Go 呼叫 C 的介面)。作者宣稱如此即可產出在各 Linux 發行版間更通用的「單一靜態執行檔且可用 GPU 繪圖」,並提供範例執行檔與以 `GOOS=musl GOARCH=amd64 gd build` 交叉編譯的方式(目前仍要求系統有 gcc,因為尚未把輔助程式內嵌)。
Hacker News 討論把焦點拉回「靜態連結 vs 動態連結」的長期爭論:有人認為共享函式庫本來就是為了更好的取捨而設計,大家卻又想把一切打包成單檔,甚至用容器把兩邊的缺點疊加;也有人反駁動態連結常因 ABI 不穩、版本地獄與符號相容問題而失效,若能像 Windows API 那樣強調向後相容,吸引力會高很多。另一派則引用反對動態連結的經典觀點,主張靜態連結在某些情境反而更小、更快,真正讓體積爆炸的是資產檔或龐大的容器底層,而不是連結方式本身。
實務面上,留言也補充替代路線與限制:不少人認為二進位相容性痛點主要集中在閉源軟體或遊戲,開源軟體在 Debian 這類發行版多半由套件系統從原始碼重建並統一相依,Steam runtime 也大幅緩解遊戲相容性;反之,凍結與捆綁相依常只是把「相依地獄」換個形式搬家。至於「把 .so 都打包帶著走」的工具選項,常被提到的有 AppImage(把應用程式與相依打包成單一檔案)、Flatpak、Snap、Nix/Guix 的 bundle/pack、或乾脆用 Docker 映像檔,但也有人分享 AppImage 可能踩到 FUSE、glibc 符號版本、musl 不相容與可執行權限等問題;另外即便走靜態路線,只要牽涉到系統圖形堆疊與 NVIDIA 專有驅動等閉源元件,仍可能卡在授權與技術邊界,讓「單一檔案跑遍所有 Linux」更像是一場高成本的工程特技。
👥 41 則討論、評論 💬
https://news.ycombinator.com/item?id=46762882