MinGW 已经支持 gcc 4.5 了,它是目前支持 C++0x最完整的编译器了。我用它成功的写了些自己好玩的项目。
不过这个发行版并不完整支持 gcc 的 C++ 标准线程库,看了些资料,要修改一下它带的 C++ 标准库代码,重编译就可以。研究了一天,终于搞定了,主要参考了这篇文章,但是也还是要有些改动。记录一下。
首先是环境,gcc 4.5用的 C++ 库是 libstdc++ v3,这个库的完整代码包含在 gcc 代码里,去 GNU 下载一份 gcc 4.5 的代码,把 libstdc++ 拿出来即可。
其次 libstdc++ 的线程是基于 pthread 的,在 Windows 下面现在有几种办法使用 pthread:一是 pthread-win32 库,这是个开源的 pthread 实现,很幸运 MinGW 发行版里面已经带了这个库;另一个可能的办法是微软自家的 Subsystem for Unix-based Applications (SUA),它在 Windows 7 Ultimate 和 Windows Server 2008 R2 上面是可选装的 Windows 组件,我还没有尝试,以后有空玩玩。
然后是修改代码和编译:
- 修改 MinGW/lib/gcc/mingw32/4.5.0/include/c++/mingw32/bits/error_constants.h
里面的 operation_not_permitted = EPERM 这一行被注释掉了,取消注释 - pthread 中最重要的数据结构:线程标识 pthread_t,在 pthread-win32 下面是一个 struct,而 libstdc++ 假定它可以比较大小,这样编译会出错,所以要在 MinGW/include/pthread.h 里 pthread_t 定义之后加上一段:
inline bool operator<(pthread_t left, pthread_t right){return left.p < right.p;}
这个比较当然很不严谨,不过够用了。
- MinGW 在编译 libstdc++ 的时候,由于相应的编译开关没打开,所以以下四个文件的内容没编译进去,从 libstdc++ 里面拷出这四个文件来,准备自己编译:mutex.cc, atomic.cc, conditional_variable.cc, thread.cc
- 文件 atomic.cc 的第一行是
#include “gstdint.h”
这个文件并不存在,其实这个文件原本应该由配置工具生成,用来控制包含的整数类型,我就自己人肉生成一个 gstdint.h,只要一行:
#include <stdint.h>
把它和 atomic.cc 放在同一个目录下 - 编译前最后一步,加上必要的宏定义,我尝试下来,最小集合似乎是
#define _GLIBCXX__PTHREADS
#define _GLIBCXX_HAS_GTHREADS
#define _POSIX_TIMEOUTS=1
这几个既可以加在代码里,也可以加在编译器开关里,我用 Code::Blocks ,于是也可以加在 IDE 选项里
之后用 MinGW 把这四个文件编译成 library,然后在自己的代码里链接到它就行了。我参考的文章里建议用 ar 把编译的 .o 文件加到 libstdc++.a 里面,这也是个办法。