繁体   English   中英

不同的 MinGW-w64 版本会破坏 DLL 加载

[英]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» 中找到。

这里需要注意的有趣点是:

  • 它将 glome.exe 视为一个 DLL,不同于我在网上找到的所有错误实例,它将可执行文件放在标题上,但在消息正文中放置了一个实际的 DLL;
  • 所需的符号可以在配套文件 libogg-0.dll 中找到;
  • 如果我用 Wine 在 Linux 上运行它,它就可以工作;
  • 如果我将二进制 glome.exe 与 Ubuntu 19.10 中内置的一个交换,它就可以工作;
  • 两个版本(Ubuntu 19.10 和 Ubuntu 20.04)使用完全相同的编译器参数,由 CMake 生成。

这是编译游戏文件之一的命令行(有很多文件,但都是用同样的方式编译的):

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

问题:

  • 为什么 Ubuntu 20.04 构建在 Wine 上工作但在 Windows 上不起作用,而 Ubuntu 19.10 构建在这两个上都工作?
  • 如何修复 Ubuntu 20.04 版本以在 Windows 上运行?

在 mingw-w64 IRC 频道闲逛后,那里的人建议我在依赖项跟踪器中打开可执行文件,这突出了工作二进制文件和损坏二进制文件之间的巨大差异:看起来符号要求从一个 DLL“泄漏”到另一个不相关的 DLL 中,动态链接库。

并排依赖行走

是什么促使那里的人们仔细研究了 DLL 导入库。 特别是,我通过 MSVC 生成的导入库链接了一些 DLL,即: glew32.libOpenAL32.libSDL2.lib

似乎 GNU ld在处理来自 MSVC 的导入库时遇到了麻烦,修复只是直接链接到 DLL 文件,在这种情况下,符号加载代码是由ld本身生成的(这实际上是一个更好的支持操作:始终链接到如果可能,直接导入 .dll,GNU 工具链中不需要导入库)。

我不知道为什么它以前有效,显然在我使用的版本中 GNU ld存在回归。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM