建構系統、函式庫與相依性

函式庫版本與 ABI 相容性

當系統上某個共享函式庫被更新時,每個用到它的程式下次執行時就突然拿到新版本——而且沒有重新編譯。為了讓這安全,新函式庫必須仍能契合那些對著舊版建出來的程式。函式庫版本控制就是一套標籤與規則,讓函式庫能演進、同時清楚地示意舊程式是否還能繼續使用它;ABI 相容性則是其中那個明確的問題:二進位介面有沒有保持不變。

ABI(應用二進位介面)是已編譯程式與已編譯函式庫之間的底層契約:結構的確切佈局、型別的大小、引數如何傳遞、函式的精確名稱與簽章。如果一次函式庫更新讓 ABI 保持不變——只修臭蟲、或新增函式而不改動既有的——舊程式就原封不動地照常運作;這是一個向後相容的改動。如果它改了 ABI——重排某結構的欄位、移除一個函式、改了一個參數——舊程式在載入它時就可能當掉或行為失常。函式庫用版本號示意這點(常用 major.minor.patch 的方案,並內嵌一個 soname):提升主版本號宣告「ABI 破了;別假設舊程式還能用」,而次版本與修補號的提升則承諾相容。

為什麼重要:ABI 相容性是那套安靜的機制,讓系統能更新一個共享函式庫去修補安全漏洞、而你所有程式都不必重建就受益。它也是常見的痛源:裝了一個 ABI 改了、版本號卻沒正確提升的函式庫,原本運作良好的程式就開始以令人困惑的方式當掉。這有別於 API(原始碼層級的介面):程式碼可以維持 API 相容——它仍編得過——卻破壞了 ABI,於是重新編譯能修好它,光換掉函式庫檔卻不行。

libfoo.so.2.3.1 ^ ^ ^ | | 修補號:純粹修臭蟲,ABI 不變 | 次版本:新增函式、舊的不變(相容) 主版本:ABI 破了——舊程式必須重建 soname(例如 libfoo.so.2)把一個程式綁到某個相容的主版本上。

主版本號的提升警告 ABI 已改變;次版本與修補號的提升則承諾舊程式仍能運作。

API 相容(原始碼仍編得過)與 ABI 相容(已編譯的二進位介面不變)是不同的。一個改動可能保住 API 卻破壞 ABI,於是對著新函式庫重新編譯能修好它,但光把新的 .so 放進去卻不行。

又称
sonamebinary compatibilityABI compatibility二進位相容版本控制