在跨平臺開發中,跨越系統、編譯器、匯編語法是經常碰到的事情,前段時間就為在mingw下編譯hans boehm gc傷神過。
現把我的解決過程記錄如下。
首先,請確保您已安裝好msys、mingw、gcc4.3.3編譯環境,gcc4.3.3為我所用的版本,如有新版,那么更好。
codeblocks用戶請暫時放棄IDE環境,習慣一下bash吧。
接下來,在msys目錄中運行msys.bat

啟動windows下的bash環境。哦,msys的叫sh,反正都是xxsh,也不用太講究了。

接下來,進入您下載的hans boehm gc 7.1解壓目錄,鍵入:
./configure --enable-shared=no --enable-static=yes --enable-cplusplus --enable-large-config --enable-parallel-mark --enable-threads=win32
為什么后面要配置這么多呢,讓我一項一項解說一下吧:
--enable-shared=no 是否編譯動態庫,我個人選否,所以填的=no,如果要編譯為動態庫,那記得把這個改為=yes啊
--enable-static=yes 是否編譯靜態庫,我個人選是,所以填的=yes,如果要編譯為動態庫,那記得把這個改為=no啊
所以呢,記得,上面這兩項最好反著填
--enable-cplusplus 允許c++
--enable-large-config 允許申請大塊內存的配置
--enable-parallel-mark 允許并發環境的標記,多線程環境一定得加上這一項
--enable-threads=win32 線程模型,這里為win32(話說當初在doc目錄里看了好久,都沒翻到到底有那幾個模型標志,索性在configure.ac里自己翻出來得了)
好了,現在輸入回車,autoconf會自動為您配置好makefile。
接下來呢,make吧:
make
呃,這里,編譯到某個文件的時候,會報一個錯:
libatomic_ops/src/atomic_ops/sysdeps/gcc/x86.h (114)
inline asm error : input constraint with a matching output constraint of incompatible type!
哇咧,這是蝦米錯誤,gc干匯編貂事情啊?
沒辦法,hans boehm還寫過一個libatomic_ops(原子操作庫),自家人當然更喜歡用自家庫咯。
好吧,看看到底是什么問題,改改看先。
打開x86.h,定位到114行,發現如下代碼:
unsigned char oldval;
/* Note: the "xchg" instruction does not need a "lock" prefix */
__asm__ __volatile__("xchgb %0, %1"
: "=q"(oldval), "=m"(*addr)
: "0"(0xff), "m"(*addr) : "memory");
天殺的,gcc嵌入的匯編啊,看著頭會很疼的啊...
趕緊翻翻AT&T語法,再找找gcc asm資料,哦,知道了gcc嵌入匯編語法如下:
__asm__(匯編語句模板: 輸出部分: 輸入部分: 破壞描述部分)
前面說輸入跟輸出的類型約束不匹配,那先看*addr,這個玩意在輸入跟輸出里長得一個模樣嘛,應該不是它的問題
剩下的就是 oldval 跟 0xff 了,這兩一個是 unsigned char ,一個是立即數,當然配不上了,不過這個0xff也太
magic num了吧,到底是啥東西啊,回頭,打開libatomic_ops/src/atomic_ops/sysdeps/msftc下的x86.h
看看同樣的函數里,vc里咋寫的:
__asm
{
mov eax,AO_TS_SET ;
mov ebx,addr ;
xchg byte ptr [ebx],al ;
}
噢噢,是AO_TS_SET,這樣有意義多了嘛,好了,我們改這么一改:
__asm__ __volatile__("xchgb %0, %1"
: "=q"(oldval), "=m"(*addr)
: "0"((unsigned char)AO_TS_SET), "m"(*addr) : "memory");
可能有同學會問,為什么0xff可以直接換成上面這個樣子了,這可是匯編啊
恩,介個嘛,括號里的東西還是按c/c++語法來的,gcc會認的,放心咯。
恩,再編譯吧:
make
……
……
……
當當當當,編譯完成,到.libs目錄里翻libgc.a去吧
附注:還記得前面的--enable-shared=no --enable-static=yes么
如果你配置了--enable-static=yes,卻沒有配置--enable-shared=no
那么在make快結束,生成庫的時候,你就會看見一串的以GC_開頭的未定義符號
這是為啥咧,就因為允許了生成靜態庫,確沒有禁止生成動態庫,配置出來的
makefile默認會先生成動態庫,也就是在未定義符號錯誤前你會發現:
gcc -shared
字樣,這是在生成動態庫,然而允許靜態庫時禁用了所有的導出符號,鏈接動態庫就咯屁咯。
所以,要么--enable-shared=no --enable-static=yes,要么--enable-shared=yes --enable-static=no
免得出錯。
終于寫完了,您也看完了,那么,下回見了。