给出一个简单的程序:
#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文件链接到程序?
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.o由mingw32.a它构成了MinGW的运行时的一部分确实打电话给你的WinMain。
有两种方法可以确保WinMain从您的文件中a.a获取:
使用-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)第二种方法是包括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否则链接器将找不到它。