在移植Cyrus sasl(cyrus-sasl-2.1.23)库时碰到如下问题(使用mingw编译):
fu000001.o:(.idata$2+0xc): undefined reference to `libmsvcrt_a_iname' fu000004.o:(.idata$2+0xc): undefined reference to `libmsvcrt_a_iname' fu000006.o:(.idata$2+0xc): undefined reference to `libmsvcrt_a_iname' fu000008.o:(.idata$2+0xc): undefined reference to `libmsvcrt_a_iname' nmth000000.o:(.idata$4+0x0): undefined reference to `_nm___iob' collect2: ld returned 1 exit status mingw32-make[2]: *** [debug\libsasl.dll] Error 1 mingw32-make[1]: *** [debug] Error 2 mingw32-make: *** [sub-lib-make_default-ordered] Error 2 The process "E:\QtSDK\mingw\bin\mingw32-make.exe" exited with code 2.
下面描述一下解决过程:
1)首先是上网搜索:看他人是怎么解决的。有数十个有关这个问题的帖子,绝大多数没有说是什么原因,不了了之。有人说是链接库的顺序问题,我调整了半天链接库顺序,均没有效果。另外添加了各种可能的库还是无效。win32: { # LIBS += -lws2_32 -ladvapi32 -lmingw32 LIBS += -lmsvcrt -ladvapi32 -lws2_32 }2)看来只好做加减法找出问题代码位置了。由于这个函数库依赖性很强,无法通过去掉某个.c文件的方式来定位问题所在。于是只好找最可能出问题的文件依次去掉函数的实现代码,然后再尝试编译直到上述链接问题消失。在问题消失后再依次恢复去掉的代码,再次编译,从而定位问题所在。在若干次尝试后终于找到了问题所在:
fprintf(stderr, "%s", prompt); (void) fflush(stderr); for (p=pbuf; (c = _getch())!=13 && c!=EOF;) { if (p < &pbuf[sizeof(pbuf)-1]) *p++ = (char) c; } *p = '\0'; fprintf(stderr, "\n"); (void) fflush(stderr);
#define stderr (&__iob_func()[2])尽然在VS2005的stdio.h文件中,难怪要与msvcrt沾边。 具体到我这里的问题,没有再纠结stderr,临时用perror函数替代了fprintf函数及stderr的使用。即:
#ifdef WIN32 perror(prompt); #else fprintf(stderr, "%s", prompt); (void) fflush(stderr); #endif for (p=pbuf; (c = _getch())!=13 && c!=EOF;) { if (p < &pbuf[sizeof(pbuf)-1]) *p++ = c; } *p = '\0'; #ifdef WIN32 perror("\n"); #else fprintf(stderr, "\n"); (void) fflush(stderr); #endif此链接问题消失。
需要说明的是:这个库用VS编译没有问题(我没有使用该库自带的NTMakefile文件,而是在QtCreator下创建.pro用VS2005编译成功)。由于我的另一个项目用到了pthread,是用mingw编译的,因此这个库也需要mingw编译。
遗留问题:尚不明确mingw为何会使用VS的stdio.h文件,以及如何避免引用VS的头文件,有兴趣的朋友可以研究一下。若解决的话,不妨反馈一下。