在跨平台开发中,跨越系统、编译器、汇编语法是经常碰到的事情,前段时间就为在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
免得出错。
终于写完了,您也看完了,那么,下回见了。