我司给客户开发客户端工具,号称「跨平台」,其实,在此之前,只是跨了两个平台:windows
和 linux
, mac
平台最近因为小明的加盟才得以支持,蛤蛤。
linux
下跨平台倒好办:主流的 Debian
系的下面的 deb
包和 RedHat
系的 rpm
包都可以很方便地编译、打包。
mac
平台下也容易折腾,和 linux
同宗同源,都是自己人,移植下来也不是难事。
恶心我的是 windows
编译环境。
windows
下面的编译工具用的是 mingw
,呵呵,大名鼎鼎的 mingw
。But,这套编译环境真的是 too old:系统是 xp sp2
,1/11/2006
年装的系统(都满十周岁了耶),一个 512MB
内存的虚拟机,不知道哪位前辈在 2009
年装完 mingw
后 C 盘
只剩下 700
多 MB 了,不能升级系统到 sp 3
,不能升级 mingw
,不然硬盘空间不足,升级失败,回滚,小可屡败屡试、屡试不爽。
软硬件条件如此之差,以至于都不能装个像样版本的 svn
,用 SSH
图形界面拷贝文件还会显示乱码。我忍了,还好我只拿这东西编译下 windows
平台的命令行客户端,每次编译完、用 SSH
copy
到别的开发机器,copy
完走人,连眼珠子都不转过去一下,真的是太 ugly
、太 disgusting
了。
为什么不重新搞一套 mingw
编译环境?一直以来都有这股冲动,最近闲了几天,终于下定决心,把这个坑填了。
考虑到兼容性,系统这次还是选择了 winsdows xp
,不过是 sp 3
了, 首先来点体力活,重新装个 mingw
,从 3.4.5
升级到 4.5.2
。
接下来,正式开始编译,出问题了:
坑之一
1 | In file included from ../include/jpeglib.h:30:0, |
好熟悉的编译 Error:类型声明冲突。
由于 #include <windows.h>
, 这个头文件经过几层 include
后会引入 rpcndr.h
头文件,人家在第 52
行已经声明 boolean
为 unsigned char
了:
1 | 51: typedef unsigned char byte; |
然后该 .cpp
文件又在 windows.h
后 #include "jpeglib.h"
,而 jpeglib.h
又引入 jmorecfg.h
,这个头文件的第 229
行又试图再次声明 boolean
为 int
:
1 | 221:/* |
原因找到了,解决方法也很简单:按照jmorecfg.h
中221~226
行的注释,如果在#include "jpeglib.h"
之前已声明了 boolean
类型的话,需要在前面加宏 #define HAVE_BOOLEAN
。
坑之二
1 | In file included from ../include/afp_wrap.h:18:0, |
莫名其妙的 Error。查看了 afp.h
并没有所说的 (
和)
、 {
和}
括号不匹配的情况啊?初步怀疑是经过预处理后,头文件被#define
指令篡改了。为了验证此想法,使用 g++ ... -E -o
生成经过预处理后的源文件。果然,有这么段:
1 | enum error_type{ |
对应的头文件afp.h
在 170
行附近内容:
1 | 169: enum error_type{ |
看样子是 NOERROR
被其他 define
指令替换成 ((HRESULT)0x00000000L)
了。
在 windows 系统中,NOERROR
是系统的一个预定义符号。该.cpp
文件首先 #include <windows.h>
,该头文件又会引入 winerror.h
,在此头文件第 1888~1913
行:
1 | 1888: |
因此, NOERROR
—> ((HRESULT)0x00000000L)
。
由于先引入了windows.h
,再引入afp_wrap.h
,导致 #include <windows.h>
这行代码后面所有被引入的文件都会将 NOERROR
替换成 ((HRESULT)0x00000000L)
了,这就是 ((HRESULT)0x00000000L) = 0,
的原因。
可以看出,当年写这个头文件的人有两大问题:
- 对 windows 不熟悉。
NOERROR
是windows
系统的预置常量啊,亲~ - 不专业。一般在头文件中声明常量名都会加个公司名或项目代号之类的前缀,就是未来避免和系统中已存在或其它项目中的常量名同名。
解决办法:我是不敢乱改 afp.h
的这位 Zorro “大神”的代码哦~To make compiler happy,姑且先#include "afp_wrap.h"
,再#include <windows.h>
。
坑之三
还有些小坑,都 one by one
地 fix
了~