为什么与 `mingw32` 链接解决了 SDL2 的这个编译问题?
Why does linking with `mingw32` solve this compilation problem with SDL2?
我正在 Windows 和 Mingw 上使用 SDL2 和 C 学习开发。
我尝试了以下命令来编译我的程序:
gcc -IC:C:/msys64_new/mingw64/include/SDL2 *.c -o game.exe -g -Wall -Wno-unused -LC:/msys64_new/mingw64/lib -lSDL2main -lSDL2
它给出了错误:Undefined reference to WinMain
然后我读到我应该在命令中添加-lmingw32
:
gcc -IC:C:/msys64_new/mingw64/include/SDL2 *.c -o game.exe -g -Wall -Wno-unused -LC:/msys64_new/mingw64/lib -lmingw32 -lSDL2main -lSDL2
现在可以了!我的问题是:
为什么这样解决问题?与 libmingw32.a
链接能解决这个问题吗?
gcc
如何找到libmingw32.a
? -LC:/msys64_new/mingw64/lib
.
指向的文件夹里好像没有这样的文件
libmingw32 是 C 运行时库的 mingw 实现的一部分,包括例如crt0 和线程本地存储,在调用 main
之前发生的事情。如果你要求 gcc 通过 gcc -v the_rest_of_your_build_command
告诉你它在后台做了什么,你会发现它的 linking 命令中有 -lmingw32
;可以删除 CRT(和 CRT0),但这是另一个问题(并且您需要特殊处理,因为普通的 C 程序期望 CRT 存在)。
有一些预定义的路径 linker 在其中搜索库。从历史上看,类 unix 系统有 /lib
、/usr/lib
等。由于 mingw 大部分只是移植的 gcc 工具链,它继承了相同的路径,只是带有它的安装目录前缀(例如 c:\mingw-w64\x86_64-w64-mingw32\lib
。检查 ld --verbose
输出,特别是 SEARCH_DIR
。
现在为什么你需要指定 -lmingw32
,即使它在那里 - 唯一的原因是 ld linker 如何解决依赖关系 - 基本上是从左到右的规则。如果一个静态库依赖于另一个静态库,则需要首先在库列表中指定它(但可以多次指定,不会产生冲突)。在您的情况下,#include <SDL.h>
将您的 main
函数重新定义为 SDL_main
;这样你的程序就不再有定义的入口点,但是 libSDL2main.a
有一个 - 简单的 main
或 WinMain
做最少的准备并调用你的 SDL_main
。因此,您需要 link 和 -lSDL2main
,但默认情况下,-lmingw32
附加在最后(导致例如 -lSDL2main -lSDL2 -lmingw32
),并且 link 不要搜索对于 SDL2main
中 WinMain
的定义,而您的 .o
中没有 WinMain
,因此出现 linking 错误。如果你添加 -lmingw32 -lSDL2main -lSDL2
,你有正确的依赖链——CRT0 依赖于 WinMain
,它在 SDL2main
中实现,它也依赖于 SDL2
。默认参数仍会在尾部添加 -lmingw32
,因此您将隐含地拥有它两次,但正如我之前所说,您可以这样做。
我正在 Windows 和 Mingw 上使用 SDL2 和 C 学习开发。
我尝试了以下命令来编译我的程序:
gcc -IC:C:/msys64_new/mingw64/include/SDL2 *.c -o game.exe -g -Wall -Wno-unused -LC:/msys64_new/mingw64/lib -lSDL2main -lSDL2
它给出了错误:Undefined reference to WinMain
然后我读到我应该在命令中添加-lmingw32
:
gcc -IC:C:/msys64_new/mingw64/include/SDL2 *.c -o game.exe -g -Wall -Wno-unused -LC:/msys64_new/mingw64/lib -lmingw32 -lSDL2main -lSDL2
现在可以了!我的问题是:
为什么这样解决问题?与
libmingw32.a
链接能解决这个问题吗?gcc
如何找到libmingw32.a
?-LC:/msys64_new/mingw64/lib
. 指向的文件夹里好像没有这样的文件
libmingw32 是 C 运行时库的 mingw 实现的一部分,包括例如crt0 和线程本地存储,在调用 main
之前发生的事情。如果你要求 gcc 通过 gcc -v the_rest_of_your_build_command
告诉你它在后台做了什么,你会发现它的 linking 命令中有 -lmingw32
;可以删除 CRT(和 CRT0),但这是另一个问题(并且您需要特殊处理,因为普通的 C 程序期望 CRT 存在)。
有一些预定义的路径 linker 在其中搜索库。从历史上看,类 unix 系统有 /lib
、/usr/lib
等。由于 mingw 大部分只是移植的 gcc 工具链,它继承了相同的路径,只是带有它的安装目录前缀(例如 c:\mingw-w64\x86_64-w64-mingw32\lib
。检查 ld --verbose
输出,特别是 SEARCH_DIR
。
现在为什么你需要指定 -lmingw32
,即使它在那里 - 唯一的原因是 ld linker 如何解决依赖关系 - 基本上是从左到右的规则。如果一个静态库依赖于另一个静态库,则需要首先在库列表中指定它(但可以多次指定,不会产生冲突)。在您的情况下,#include <SDL.h>
将您的 main
函数重新定义为 SDL_main
;这样你的程序就不再有定义的入口点,但是 libSDL2main.a
有一个 - 简单的 main
或 WinMain
做最少的准备并调用你的 SDL_main
。因此,您需要 link 和 -lSDL2main
,但默认情况下,-lmingw32
附加在最后(导致例如 -lSDL2main -lSDL2 -lmingw32
),并且 link 不要搜索对于 SDL2main
中 WinMain
的定义,而您的 .o
中没有 WinMain
,因此出现 linking 错误。如果你添加 -lmingw32 -lSDL2main -lSDL2
,你有正确的依赖链——CRT0 依赖于 WinMain
,它在 SDL2main
中实现,它也依赖于 SDL2
。默认参数仍会在尾部添加 -lmingw32
,因此您将隐含地拥有它两次,但正如我之前所说,您可以这样做。