看了好多回答,還是覺得有更本質的原因的,根源還是在C++這個語言特性上
為什麽C++沒有Python之類語言這樣活躍的生態?我覺得根本原因在於C++沒有解決好一個問題: 菱形依賴
什麽叫菱形依賴呢?就是說A依賴B,A也依賴C,但是B和C同時依賴D,並且我們限定D並不是STL這樣的標準庫,BCD都是開源庫。為了限定到C++,我們這裏BCD都是C++庫,采用源碼的方式釋出。
這種情況在生態活躍的語言中則是非常常見的。
在C++當中會怎樣呢?
- B和C中至少一個將D的源碼合並到了自己的源碼裏面,放到thirdparty之類的目錄裏面。A將兩份原始碼加自己的一起放到thirdparty裏面, 編譯,符號沖突,爆炸 。
- B和C在install說明中提到,必須把依賴放到某個地方,然後修改Makefile/CMAKE/Bazel配置,將D的源碼目錄加進來。結果B和C編譯出來的.a裏面還是帶著D的全部符號,A嘗試二進制連結, 符號沖突,爆炸 。
- B和C在install說明中提到,需要將D的依賴放在某個地方,先編譯成.a,設定好參數直接連結.a。但是B和C要求的D的編譯參數不一樣, 連結不到一起,爆炸 。
- 把所有的依賴都一個一個放在獨立的位置上,設定好include目錄,每個都用自己的Makefile獨自編譯成.a,編譯參數用同一套,最後再一個一個指定起來連結到一起—— 人工成本爆炸 。
- A希望B和C透過動態連結方式連線,方便升級。動態連結柯瑞面連結了D的符號, 載入起來符號沖突,爆炸 。B和C一個動態連結了D,一個靜態連結了D, 還是符號沖突,爆炸 。
- D把自己改成了header only的庫,終於不需要單獨編譯了。B和C在參照D的時候設定的宏不一樣,導致 編譯出的弱符號不相容,連結完執行崩潰,爆炸 。
以上種種,最後對於C++庫的作者來說,就變成了這樣一個結果:
如果我要提供一個好用、好編譯、不給我天天找事情的庫,那麽我不能參照其它的開源庫
沒有比這更矛盾的事情了,要造輪子,第一件事情是不能用別人的輪子。但是如果你要正經開發一個系統,你能保證自己不會有一天需要把這個程式碼重構成一個通用的庫嗎? 那你就得從第一天開始避免用第三方開源庫……
在Linux上面唯一有點生態的意思的做法,是參照yum/apt源裏面的xxx-dev這樣的庫,這些庫透過pkgconfig的方式組織,而且透過包管理系統保證大家下載到的都是相同且相容而且編譯好了的二進制庫,參照起來很方便。但是,只有把介面限定到純C才能釋出確保二進制相容的庫,那折騰了半天,就算內部是C++開發的,一到庫的邊界上還得轉成純C,也就失去了C++語言的優勢了。