用 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 政策也有點關係。

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


留言列表 (3)

發表留言
  • damody
  • 請問一下,如果使用 msvc-9.0 要編譯出像directx sdk那種通吃/MT /MTd /MD /MDd的lib要怎麼設定?
  • --build-type=complete

    最好確定硬碟夠大
    不過有些組合仍然不會build

    novus 於 2010/08/28 13:30 回覆

  • damody
  • sorry,我的問題可能不夠清楚,我想知道的是有沒有辨法把/MT /MTd /MD /MDd的編譯結果只編譯出一個lib檔,我看directx sdk的lib雖然只有分x86跟x64,但卻可以給msvc也可以給mingw吃,而且通用各種組態,感覺好像是隱藏功能?
  • 對 Boost 來說不可能,因為 signature 會衝突。對一些肯定不會產生衝突的 variant,是有可能用工具把 lib 裡的 obj 檔拆出來重新包成一個。不過我看不出這麼作有什麼意義,只要啟用 VC 的 Autolink 功能,不管你選項怎麼變都應該會對應到正確的lib上(除非你沒有建置該lib...)


    我不清楚 directx sdk 實際使用的連結機制,亂講怕有錯。
    我想你必須先了解 /MD /MTd 等等說穿了只是指定 msvcrt 的版本,以及定義幾個 macro。如果 lib 對這些都不在乎的話,不管你下什麼選項其實都沒差。另外他也有可能用一些 macro trick 產生正確的 signature;又或者他根本不是在編譯期連結,而是透過其他機制動態載入,例如背景作業的 LoadLibray/COM。

    我比較好奇的是你確實可以用 VC 和 MinGW 連結相同一個 lib,不用 reimp 過?我記得以前沒這麼簡單

    novus 於 2010/08/30 01:38 回覆