用 GCC 4.5 編譯 Boost 1.44 遇到第一件感到猶豫的事,就是 runtime-link 該用 static 還是 shared。在 VC 通常想都不用想就選 shared,然後發動坊間熱賣的白癡念力術,妄想其他電腦都出現正確版本 VC runtime。

在 GCC 4.4 之前,MinGW 對標準程式庫都是預設為 static,而且 libstdc++ 還在可接受的體積內,所以我也沒有太關心這個選項。動態連結 libgcc 和 libmingw32 似乎沒甚麼道理,靜態連結可以省掉一堆鳥事。然而見識過靜態連結libstdc++ v3 所帶來的肥大程式碼:直接 cout 出 hello world 就直逼驚人的 1 Mb,就算 strip 過還是大於 500k,如果常撰寫小程式可能得好好考慮動態連結。

我想先以 runtime-link=static 實驗看看,根據已知經驗, link=shared 配 runtime-link=static 建不起來,即使硬建出來也很可能出問題,所以我的 link 都是 static。

編完後,我先用個小程式測 regex,只要編譯時附加 -static 就搞定了,只是執行檔和意料中的一樣肥大。

然而測試 thread 的時候還有點鳥,加了 -static 卻跑出了一堆 _imp__XXX 未定義錯誤訊息。多虧我還有點經驗,馬上就知道這是因為編譯器告訴連結器 signature 當中帶有 __declspec (dllimport),但連結器卻拿到靜態版的 lib。一時之間也沒啥好辦法,我直接掃描了一下 Boost.Thread 的 header,得知可以用 -DBOOST_THREAD_USE_LIB 產生無 dllimport 的宣告。

萬萬沒想到這樣卻發生了多重定義的問題,看一下衝突的名稱大概知道來自於 MinGW Runtime,通常是因為程式庫當中某些該用 extern 的地方卻直接定義所造成的。上網看了一下 Boost 的 Bug list,上面說是 mingwrt-3.18 的 bug,所以退回去用 mingwrt-3.17 就沒事了。

以上就是一些鳥事,花了我一點時間,希望可以省下其他人的時間。如果有人知道 Boost.thread 比較「正確」的靜態連結方式也歡迎告知。

 


 

註1:隨著 GCC 對 C++ 1x 支援度提升,libstdc++ v3 帶來大量程式碼應該是趨勢之必然,最終連結出肥大的執行檔其實不應該怪 lib,而是連結器的問題。目前 GCC ld 的做法是只要一個 .a 檔中的某個 .o 被使用到,哪怕用到的只是單個函數、一個小小的變數,ld 都會把整個 .o 搬到連結目標裡。

註2:MinGW 開始預設動態連結除了 lib 變肥有關之外,我猜和 GCC 的 license 政策也有點關係。

arrow
arrow
    全站熱搜

    novus 發表在 痞客邦 留言(3) 人氣()