[英]Different MinGW-w64 version breaks DLL loading
我有一个主要是在 Ubuntu 下开发的开源游戏项目。 最近我将它移植到 Windows,只包括一些小的调整,然后为 Windows 构建它,因为我只使用跨平台库和功能。
为了构建它,最初我使用 Ubuntu 19.04 存储库中的 MinGW-w64 进行交叉编译,它的工作原理非常棒。 这是它报告的版本:
$ x86_64-w64-mingw32-g++-posix --version
x86_64-w64-mingw32-g++-posix (GCC) 9.2-posix 20191008
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
当我更新到 Ubuntu 20.04 时,MinGW-w64 的版本号有一个小问题:
$ x86_64-w64-mingw32-g++-posix --version
x86_64-w64-mingw32-g++-posix (GCC) 9.3-posix 20200320
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
更新破坏了我的构建,因为新版本的 MinGW-w64 生成的可执行文件不起作用。 在 Windows 机器上执行时,无法从其 DLL 依赖项中找到符号,并且出现以下弹出错误:
这应该翻译成英文版的错误消息(填充变量):
glome.exe - 未找到入口点
过程入口点 ogg_page_bos 无法在动态链接库 «path to glome.exe» 中找到。
这里需要注意的有趣点是:
这是编译游戏文件之一的命令行(有很多文件,但都是用同样的方式编译的):
cd /home/lucas/glome/ubuntu-20.04-win-build/src/sdl && /usr/bin/x86_64-w64-mingw32-g++-posix @CMakeFiles/glome.dir/includes_CXX.rsp -march=haswell -mtune=generic -Ofast -fno-fat-lto-objects -flto=12 -I/home/lucas/glome/windows-deps/opusfile/include/opus/ -I/home/lucas/glome/windows-deps/opus/include/opus/ -I/home/lucas/glome/windows-deps/libogg/include/ogg/ -I/home/lucas/glome/windows-deps/glew-2.1.0/include/ -I/home/lucas/glome/windows-deps/OpenAL-1.1-SDK/include -I/home/lucas/glome/windows-deps/libogg/include -I/home/lucas/glome/windows-deps/SDL2-2.0.12/include/ -I/home/lucas/glome/windows-deps/boost_1_72_0/ -g -std=gnu++17 -o CMakeFiles/glome.dir/input.cpp.obj -c /home/lucas/glome/src/src/sdl/input.cpp
其中CMakeFiles/glome.dir/includes_CXX.rsp
仅包含-I
指令:
-I/home/lucas/glome/src/src/common/. -I/home/lucas/glome/src/external/concurrentqueue -I/home/lucas/glome/ubuntu-20.04-win-build/src -I/home/lucas/glome/src/src/sdl
可执行文件的链接命令是:
/usr/bin/x86_64-w64-mingw32-g++-posix -march=haswell -mtune=generic -Ofast -fno-fat-lto-objects -flto=12 -I/home/lucas/glome/windows-deps/opusfile/include/opus/ -I/home/lucas/glome/windows-deps/opus/include/opus/ -I/home/lucas/glome/windows-deps/libogg/include/ogg/ -I/home/lucas/glome/windows-deps/glew-2.1.0/include/ -I/home/lucas/glome/windows-deps/OpenAL-1.1-SDK/include -I/home/lucas/glome/windows-deps/libogg/include -I/home/lucas/glome/windows-deps/SDL2-2.0.12/include/ -I/home/lucas/glome/windows-deps/boost_1_72_0/ -g -Wl,--whole-archive CMakeFiles/glome.dir/objects.a -Wl,--no-whole-archive -o glome.exe -Wl,--out-implib,libglome.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/glome.dir/linklibs.rsp
其中CMakeFiles/glome.dir/linklibs.rsp
包含:
../common/libcommon.a -lopengl32 -lglu32 -march=haswell -mtune=generic -Ofast -fno-fat-lto-objects -flto=12 -I/home/lucas/glome/windows-deps/opusfile/include/opus/ -I/home/lucas/glome/windows-deps/opus/include/opus/ -I/home/lucas/glome/windows-deps/libogg/include/ogg/ -I/home/lucas/glome/windows-deps/glew-2.1.0/include/ -I/home/lucas/glome/windows-deps/OpenAL-1.1-SDK/include -I/home/lucas/glome/windows-deps/libogg/include -I/home/lucas/glome/windows-deps/SDL2-2.0.12/include/ -I/home/lucas/glome/windows-deps/boost_1_72_0/ /home/lucas/glome/windows-deps/OpenAL-1.1-SDK/libs/Win64/OpenAL32.lib /home/lucas/glome/windows-deps/glew-2.1.0/lib/Release/x64/glew32.lib /home/lucas/glome/windows-deps/opusfile/lib/libopusfile.a /home/lucas/glome/windows-deps/opus/lib/libopus.dll.a /home/lucas/glome/windows-deps/libogg/lib/libogg.dll.a -L/home/lucas/glome/windows-deps/SDL2-2.0.12/lib/x64/ -lSDL2main -lSDL2 -static-libgcc -static-libstdc++ -Wl,-allow-multiple-definition -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32
除了路径( ubuntu-20.04-win-build
vs ubuntu-19.10-win-build
),编译和链接命令完全相同,使用相同的参数从相同的CMakeLists.txt
。
问题:
在 mingw-w64 IRC 频道闲逛后,那里的人建议我在依赖项跟踪器中打开可执行文件,这突出了工作二进制文件和损坏二进制文件之间的巨大差异:看起来符号要求从一个 DLL“泄漏”到另一个不相关的 DLL 中,动态链接库。
是什么促使那里的人们仔细研究了 DLL 导入库。 特别是,我通过 MSVC 生成的导入库链接了一些 DLL,即: glew32.lib
、 OpenAL32.lib
和SDL2.lib
。
似乎 GNU ld
在处理来自 MSVC 的导入库时遇到了麻烦,修复只是直接链接到 DLL 文件,在这种情况下,符号加载代码是由ld
本身生成的(这实际上是一个更好的支持操作:始终链接到如果可能,直接导入 .dll,GNU 工具链中不需要导入库)。
我不知道为什么它以前有效,显然在我使用的版本中 GNU ld
存在回归。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.