[英]Different MinGW-w64 version breaks DLL loading
I have an open-source game project that was mostly developed under Ubuntu.我有一个主要是在 Ubuntu 下开发的开源游戏项目。 Recently I ported it to Windows, what consisted only in minor tweaks and then building it for Windows, since I only used cross-platform libraries and features.
最近我将它移植到 Windows,只包括一些小的调整,然后为 Windows 构建它,因为我只使用跨平台库和功能。
To build it, initially I cross-compiled using MinGW-w64 from Ubuntu's 19.04 repositories, and it worked like a charm.为了构建它,最初我使用 Ubuntu 19.04 存储库中的 MinGW-w64 进行交叉编译,它的工作原理非常棒。 This is what it reports as the version:
这是它报告的版本:
$ 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.
When I updated to Ubuntu 20.04, MinGW-w64 got a small bump in version number:当我更新到 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.
The update broke my build, as the executable generated by the new version of MinGW-w64 does not work.更新破坏了我的构建,因为新版本的 MinGW-w64 生成的可执行文件不起作用。 When executed on a Windows machine, it is unable to find the symbols from its DLL dependencies, and I get the following popup error:
在 Windows 机器上执行时,无法从其 DLL 依赖项中找到符号,并且出现以下弹出错误:
Which should translate to English version of the error message as (filling the variables):这应该翻译成英文版的错误消息(填充变量):
glome.exe - Entry Point Not Found
glome.exe - 未找到入口点
The procedure entry point ogg_page_bos could not be located in the dynamic link library «path to glome.exe».
过程入口点 ogg_page_bos 无法在动态链接库 «path to glome.exe» 中找到。
The interesting points to notice here are:这里需要注意的有趣点是:
This is the command line for the compilation of one of the files of the game (there are many files, but all are compiled in the same way):这是编译游戏文件之一的命令行(有很多文件,但都是用同样的方式编译的):
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
where CMakeFiles/glome.dir/includes_CXX.rsp
contains only -I
directives:其中
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
The linking command for the executable is:可执行文件的链接命令是:
/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
where CMakeFiles/glome.dir/linklibs.rsp
contains:其中
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
Apart from the paths ( ubuntu-20.04-win-build
vs ubuntu-19.10-win-build
), the compilation and linking commands are exactly the same, generated with the same parameters from the same CMakeLists.txt
.除了路径(
ubuntu-20.04-win-build
vs ubuntu-19.10-win-build
),编译和链接命令完全相同,使用相同的参数从相同的CMakeLists.txt
。
The questions:问题:
After hanging out in mingw-w64 IRC channel, people there suggested me to open the executable in dependency tracker, which highlighted a big difference between the working and broken binaries: it looks like symbol requirements "leaked" from one DLL into another, unrelated, DLL.在 mingw-w64 IRC 频道闲逛后,那里的人建议我在依赖项跟踪器中打开可执行文件,这突出了工作二进制文件和损坏二进制文件之间的巨大差异:看起来符号要求从一个 DLL“泄漏”到另一个不相关的 DLL 中,动态链接库。
What led people there to take a closer look into the DLL import libraries.是什么促使那里的人们仔细研究了 DLL 导入库。 In particular, I was linking against some DLLs via their MSVC generated import libraries, namely:
glew32.lib
, OpenAL32.lib
and SDL2.lib
.特别是,我通过 MSVC 生成的导入库链接了一些 DLL,即:
glew32.lib
、 OpenAL32.lib
和SDL2.lib
。
It seems GNU ld
has trouble handling import libraries from MSVC, and the fix was simply linking against the DLL files directly, in which case the symbol loading code is generated by ld
itself (and this is actually a much better supported operation: always link against the .dll directly if possible, import libraries are not needed in GNU toolchain).似乎 GNU
ld
在处理来自 MSVC 的导入库时遇到了麻烦,修复只是直接链接到 DLL 文件,在这种情况下,符号加载代码是由ld
本身生成的(这实际上是一个更好的支持操作:始终链接到如果可能,直接导入 .dll,GNU 工具链中不需要导入库)。
I don't know why it worked before, apparently there was a regression in GNU ld
across the versions I used.我不知道为什么它以前有效,显然在我使用的版本中 GNU
ld
存在回归。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.