从Cygwin中取出MinGW for GCC

    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. #define DLLNAMEBUFSIZE  128
  3. #define DLLNAMEBUFSIZE  128
  4. #define CMDBUFSIZE      256
  5. #define RECVBUFSIZE     256
  6. typedef struct _DllInfo DllInfo;
  7. struct _DllInfo
  8. {
  9.     char fileName[DLLNAMEBUFSIZE];
  10.     DllInfo *pNext;
  11. };
  12. DllInfo *g_pDllList;
  13. DllInfo *g_pDllListTail;
  14. void ParseDllFileNames(FILE *fDl)
  15. {
  16.     DllInfo *pDll;
  17.     char dllNameBuf[DLLNAMEBUFSIZE];
  18.     g_pDllListTail=g_pDllList = 0;
  19.     while (!feof(fDl))
  20.     {
  21.         int n = 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.         
  29.         strcpy(pDll->fileName, dllNameBuf + strlen("../bin/"));
  30.         pDll->pNext = 0;
  31.         if (g_pDllList==0)
  32.         {
  33.             g_pDllListTail=g_pDllList=pDll;
  34.         }
  35.         else
  36.         {
  37.             g_pDllListTail->pNext = pDll;
  38.             g_pDllListTail = pDll;
  39.         }
  40.     }
  41. }
  42. int CheckFileExistence()
  43. {
  44.     char recvbuf[RECVBUFSIZE];
  45.     char *pszCmd = "..//bin//ls a.exe > result.txt";
  46.     char *pszTarget = "a.exe";
  47.     FILE *f;
  48.     printf("%s/n", pszCmd);
  49.     system(pszCmd);
  50.     f = fopen("result.txt""rb");
  51.     if (!f)
  52.     {
  53.         return 0;
  54.     }
  55.     fgets(recvbuf, RECVBUFSIZE, f);
  56.     if (0 == strncmp(recvbuf, pszTarget, strlen(pszTarget)))
  57.     {
  58.         return 1;
  59.     }
  60.     else
  61.     {
  62.         printf("return 0/n");
  63.         return 0;
  64.     }
  65. }
  66. void TryAddingDlls()
  67. {
  68.     DllInfo *pDll = g_pDllList;
  69.     char *pCmdCpl = "gcc.exe a.c";
  70.     for ( ; pDll; pDll = pDll->pNext)
  71.     {
  72.         char *pszDllName = pDll->fileName;
  73.         char cmd[CMDBUFSIZE];
  74.         sprintf(cmd, "copy ..//bin//%s .", pszDllName);
  75.         printf("%s/n", cmd);
  76.         system(cmd);
  77.         printf("%s/n", pCmdCpl);
  78.         system(pCmdCpl);
  79.         if (CheckFileExistence())
  80.         {
  81.             printf(":gcc works after %s being added./n", pszDllName);
  82.             break;
  83.         }
  84.     }
  85. }
  86. int main(void)
  87. {
  88.     FILE *fDl = 0;
  89.     char *pCmd = "..//bin//ls ../bin/*.dll > dllfilelist.txt";
  90.     printf("%s/n", pCmd);
  91.     system(pCmd);
  92.     fDl = fopen("dllfilelist.txt""r");
  93.     if (!fDl)
  94.     {
  95.         printf(": Error opening the list file./n");
  96.         return 0;
  97.     }
  98.     ParseDllFileNames(fDl);
  99.     fclose(fDl);
  100.     printf(": Parsing DLL names OK./n");
  101.     TryAddingDlls();
  102.     return 0;
  103. }









posted @ 2008-09-25 12:48  quanben  阅读(271)  评论(0编辑  收藏  举报