當前位置: 華文星空 > 知識

為什麽 Go 和 Rust 常提供靜態編譯好的 Linux 程式,而 C 不行?

2019-11-13知識

……?

C最早是不支持動態連結的,那時候全都只能靜態連結,後來作業系統技術發展了才有動態連結的。靜態連結可以說是動態連結的祖宗。

一直到今天,使用靜態連結技術上也是毫無問題的,主要是這麽幾個毛病:

  1. 某些特殊的庫(主要是glibc)一般來說必須使用動態連結,因為可能跟不同版本的內核會不相容(而且glibc也是一個主要的破壞向前相容性的原因)
  2. 很多庫發行的二進制版本只有動態連結庫,要做靜態連結,需要自己從源碼編譯。C的編譯出了名的慢,要把所有依賴庫都重新靜態編譯了很費勁。
  3. 動態連結發明出來本來就是有它的優勢的,第一依賴庫可以獨立升級,尤其是對於修復安全問題很重要,而靜態連結的任何依賴庫要更新都需要整個重新釋出binary;第二包的大小也小。
  4. 混用靜態連結和動態連結也會產生嚴重問題,比如某個動態連結的庫和程式本身都使用了一個第三方庫,但使用的版本不同,一個靜態連結了低版本,一個動態連結了高版本,可能會引起嚴重的問題。

其中第二點可以認為是最關鍵的。相比來說,golang就可以做到所有的依賴都從源碼編譯,速度很快,也就沒有其他問題了。

如果連結的庫並不多,透過修改編譯選項編譯一個靜態連結的二進制檔釋出是毫無問題的,NPM社群裏面有一部份包起來的可執行程式就是靜態連結的(除了glibc等系統庫以外)

另外一個相對次要的原因是Linux社群流行這一套基於源碼autoconf然後make的工具鏈,這樣的源碼在非常多的平台和配置上都能跑起來,可玩性比較好。其他答案提到的跨架構也是一個重要的理由吧。

對了,還有一個非常非常重要的理由: LGPL授權只能動態連結,如果使用靜態連結,則整個源碼都必須變成LGPL授權。