当链接为* .a静态库时,为什么无法解析“ WinMain”?

use*_*398 3 c++ gcc mingw

给出一个简单的程序:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, 
                   LPSTR lpCmdLine, int nCmdShow)
{
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我运行g++ a.cpp,效果很好。

但是,运行g++ -c a.cpp && ar rcs a.a a.o && g++ a.a会出现以下错误:

c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/4.8.1/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况的任何见解?如何仅将.a文件链接到程序?

gre*_*olf 6

gcc ld链接器处理*.a静态库与*.o对象文件略有不同。特别是,除非目标文件或先前链接的另一个静态库使用了静态库,否则静态库中的符号不会包含在最终的二进制映像可执行文件中。

此外,您在静态库中传递的顺序对于至关重要ld。例如,say libb.a需要一个in中的函数liba.a。如果您这样链接:

g ++ -Wall example.cpp -o example.exe -la -lb

这将无法解决,因为在liba处理时它看不到符号-lb要求的内容(libb尚未处理)。从检索到的唯一标志liba.a就是一切也有过长达这一点

为什么这很重要?

如果将上述过程应用于您的问题,很清楚为什么WinMain未得到解决。

g ++ aa

ld处理过程中,a.a它说:“哦,什么都没用,WinMain所以我将不包括在内”;这一点在处理上是正确的,因为在此之前没有提供其他目标文件。

您在上面看不到的是,默认情况下,mingw 还包含一堆重要的样板代码,这些代码才能使程序正常工作。其中之一是crt0_c.omingw32.a它构成了MinGW的运行时的一部分确实打电话给你的WinMain

解决方案

有两种方法可以确保WinMain从您的文件中a.a获取:

  1. 使用-Wl,--whole-archive武力纳入所有符号的a.a所以他们可以符号解析。-Wl,--no-whole-archive之后追加,这样就不会错误地将其应用于之后的其他库。例如。

    g++ -o example.exe -Wl,--whole-archive a.a -Wl,--no-whole-archive
    
    Run Code Online (Sandbox Code Playgroud)
  2. 第二种方法是包括mingw32.a手动之前 a.a所以WinMain当成为挂起未解析的符号a.a进行处理:

    g++ -o example.exe -lmingw32 a.a
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    g++ -o example.exe libmingw32.a a.a
    
    Run Code Online (Sandbox Code Playgroud)

但是您可能需要完全限定到达的路径,libmingw32.a否则链接器将找不到它。