从Cygwin中取出MinGW for GCC

本文介绍了一个关于Cygwin环境下gcc编译器无法正常工作的案例,通过逐步加载缺失的DLL解决了问题。文章详细记录了问题排查过程及最终解决方案。
Cygwin内含MinGW,于是就把原有的MinGW卸载了。但是由于某种原因(原因在最后介绍)gcc在Windows命令行下就不起作用了(运行后并不产生编译结果),即使Path设置正确。
采用掩蔽DLL的方法。将gcc放置于一个新建的文件夹,并运行,会出现缺失DLL,逐个加上这些DLL后能执行通过,但结果仍是无法产生输出文件。估计仍是有相关的DLL没有被链入。但是使用Dependency Walker也无法发现(显然在执行而言,装入文件夹的这些DLL已经足够了)。这些DLL是:
cygwin1.dll
cygintl-8.dll
cygiconv-2.dll

于是就想通过暴力方法找到这个缺失的DLL,想法很简单,就是逐个装入Cygwin的bin文件夹下的那些DLL,直到gcc执行能输出编译结果为止,这样最后装入的那个DLL有很大的可能是唯一缺失的那个DLL。Cygwin下的DLL毛毛多,当然得用程序实现,结果发现那个依赖的DLL是cygintl-3.dll。
这个程序工具选取,编译和执行也很有讲究。如果继续用那个cygwin下的gcc会有诸多不便。于是用VC,但其中用了cygwin下的一些命令,例如ls,因为其输出结果比dir要规整。因为system命令中cd是不起作用的,最终生成文件要放在那个装有待测gcc.exe的文件夹中,这个文件夹放在Cygwin/mingw下。具体代码贴在最后。

现在讲一下产生这个问题的真正原因。这个原因很可笑,是因为存在另一个应用,它也用到了cygwin相关的dll,但版本较旧。而它的bin文件夹又在%PATH%中,而新加的bin(包括Cygwin本身的bin)都在它之后。估计DLL的搜寻也是从%PATH%中依次进行的,于是链入的都是旧版本的,从而导致错误。这样一来看来刚才的这些抽取工作都是不必要的。郁闷。
  1. #include<stdio.h>
  2. #defineDLLNAMEBUFSIZE128
  3. #defineDLLNAMEBUFSIZE128
  4. #defineCMDBUFSIZE256
  5. #defineRECVBUFSIZE256
  6. typedefstruct_DllInfoDllInfo;
  7. struct_DllInfo
  8. {
  9. charfileName[DLLNAMEBUFSIZE];
  10. DllInfo*pNext;
  11. };
  12. DllInfo*g_pDllList;
  13. DllInfo*g_pDllListTail;
  14. voidParseDllFileNames(FILE*fDl)
  15. {
  16. DllInfo*pDll;
  17. chardllNameBuf[DLLNAMEBUFSIZE];
  18. g_pDllListTail=g_pDllList=0;
  19. while(!feof(fDl))
  20. {
  21. intn=fscanf(fDl,"%s/n",dllNameBuf);
  22. if(n==0)
  23. {
  24. break;
  25. }
  26. //printf("%s/n",dllNameBuf);
  27. pDll=(DllInfo*)malloc(sizeof(DllInfo));
  28. strcpy(pDll->fileName,dllNameBuf+strlen("../bin/"));
  29. pDll->pNext=0;
  30. if(g_pDllList==0)
  31. {
  32. g_pDllListTail=g_pDllList=pDll;
  33. }
  34. else
  35. {
  36. g_pDllListTail->pNext=pDll;
  37. g_pDllListTail=pDll;
  38. }
  39. }
  40. }
  41. intCheckFileExistence()
  42. {
  43. charrecvbuf[RECVBUFSIZE];
  44. char*pszCmd="..//bin//lsa.exe>result.txt";
  45. char*pszTarget="a.exe";
  46. FILE*f;
  47. printf("%s/n",pszCmd);
  48. system(pszCmd);
  49. f=fopen("result.txt","rb");
  50. if(!f)
  51. {
  52. return0;
  53. }
  54. fgets(recvbuf,RECVBUFSIZE,f);
  55. if(0==strncmp(recvbuf,pszTarget,strlen(pszTarget)))
  56. {
  57. return1;
  58. }
  59. else
  60. {
  61. printf("return0/n");
  62. return0;
  63. }
  64. }
  65. voidTryAddingDlls()
  66. {
  67. DllInfo*pDll=g_pDllList;
  68. char*pCmdCpl="gcc.exea.c";
  69. for(;pDll;pDll=pDll->pNext)
  70. {
  71. char*pszDllName=pDll->fileName;
  72. charcmd[CMDBUFSIZE];
  73. sprintf(cmd,"copy..//bin//%s.",pszDllName);
  74. printf("%s/n",cmd);
  75. system(cmd);
  76. printf("%s/n",pCmdCpl);
  77. system(pCmdCpl);
  78. if(CheckFileExistence())
  79. {
  80. printf(":gccworksafter%sbeingadded./n",pszDllName);
  81. break;
  82. }
  83. }
  84. }
  85. intmain(void)
  86. {
  87. FILE*fDl=0;
  88. char*pCmd="..//bin//ls../bin/*.dll>dllfilelist.txt";
  89. printf("%s/n",pCmd);
  90. system(pCmd);
  91. fDl=fopen("dllfilelist.txt","r");
  92. if(!fDl)
  93. {
  94. printf(":Erroropeningthelistfile./n");
  95. return0;
  96. }
  97. ParseDllFileNames(fDl);
  98. fclose(fDl);
  99. printf(":ParsingDLLnamesOK./n");
  100. TryAddingDlls();
  101. return0;
  102. }









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值