3

给定一个简单的程序:

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, 
                   LPSTR lpCmdLine, int nCmdShow)
{
  return 0;
}

如果我运行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

关于为什么会发生这种情况的任何见解?我怎样才能链接一个只有 .a 文件的程序?

4

3 回答 3

7

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

此外,您在静态库中传递的顺序对于ld. 例如,saylibb.a需要一个位于liba.a. 如果你像这样链接它:

g++ -Wall 示例.cpp -o 示例.exe -la -lb

这将无法解决,因为在liba处理时它看不到-lb需要什么符号(libb尚未处理)。从中检索到的唯一符号liba.a是它所看到的所有内容

为什么这很重要?

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

g++ aa

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

您在上面没有看到的是,默认情况下,mingw还包含一堆重要的样板代码,以使您的程序正常工作。其中之一是mingw 运行时的一部分,它crt0_c.o确实调用了您的.mingw32.aWinMain

解决方案

有两种方法可以确保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
    
  2. 第二种方法是在so成为待处理的未解析符号之前mingw32.a手动包含: a.aWinMaina.a

    g++ -o example.exe -lmingw32 a.a
    

    或者

    g++ -o example.exe libmingw32.a a.a
    

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

于 2013-10-29T02:12:54.807 回答
0

.a 文件是静态库,就链接器而言。链接器仅从定义当前未解析符号的档案中取出对象。因此,如果没有引用 .a 文件中定义的符号的任何目标文件,它们将不会被拉入。示例中的链接器输出为空,因此未定义 WinMain。

实际上,当您定义标准 main() 时,它似乎可以工作。我认为这是因为语言标准需要对 main() 的引用。还有一个 gcc / ld 命令行选项来生成对符号的引用。尝试-u WinMain@16在 .a 文件之前添加。

于 2013-10-27T23:48:32.480 回答
0

我正在使用代码::块。今天我在静态库中遇到了与 WinMain 相同的问题。在我的情况下,更改库的顺序不起作用。我终于通过添加-lmingw32Project/Build options/Linker settings/Other linker options来解决它。

于 2014-07-22T18:07:53.317 回答