如何在MinGW中进行libwinpthread-1.dll的静态链接?

66

我使用这里提供的mingw工具链:http://sourceforge.net/projects/mingwbuilds/files/host-windows/releases/4.7.2/32-bit/threads-posix/sjlj/x32-4.7.2-release-posix-sjlj-rev2.7z/download

我已经成功地使用参数-static-libgcc -static-libstdc++来静态链接libstdc++-6.dlllibgcc_s_sjlj-1.dll,但是我找不到一个能够做同样事情的命令来链接libwinpthread-1.dll


6
为了技术上的明确,在静态链接时,您不会链接到 DLL。库libgcclibstdc++有静态和非静态(DLL)版本,如果您静态链接,则不会链接到 DLL。您应该静态链接到 pthreads 库,而不是 libwinpthread-1.dll(因为您无法静态链接到动态库...这违背了动态库的目的)。 - Cornstalks
我得到了以下错误信息:c++: error: unrecognized command line option '-static-pthreads',同样的问题也出现在winpthreads上。 - rsk82
2
小技巧:mingw附带的libwinpthread-1.dll与互联网上流传的不同。使用错误的版本将导致无限递归DLL调用(根据Dependency walker)后跟堆栈溢出。 - Mohan
只需链接 -l:libwinpthread.a - superbem
10个回答

63

如果您的工具链包括静态winpthreads,请添加选项

-static

它将拉取所有可用的库的静态版本。

或者,您可以从工具链目录中删除libwinpthread.dll.a和DLL本身。这可能会破坏与libstdc++和libgcc DLL链接的程序,所以请小心。

第三个选项是使用-Wl,-Bdynamic-Wl,-Bstatic选择要链接的版本(这就是在调用ld时-static内部执行的操作)。例如:

gcc -o someexec someobject.o -Wl,-Bdynamic -lsomelibIwantshared -Wl,-Bstatic -lsomelibIwantstatic

如果你在链接命令中加入-v选项,当你使用-static-libgcc-static-libstdc++时,你应该会看到这些选项出现在ld/collect2调用中。


36

试试这个:

-static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic

注意在-lpthread之前加上-lstdc++。这对我有效。

确保将此添加到您的g++命令行的最后。


2
很不幸,这对我来说行不通,除非我删除末尾的“-Wl,-Bdynamic”(这是无意义的)。 - rr-
@rr- 请尝试使用gcc -v打印详细信息,并将其发送给我。我会进一步研究它。 - Star Brilliant
5
我想我明白了……只有在使用静态libstdc++编译时,我才需要libwinpthread-1.dll。也就是说,在我的环境(arch和官方存储库)中,静态版本的libstdc++依赖于共享winpthread。为了避免这种情况,我可能需要自己编译mingw-w64。 - rr-
@rr- 很高兴你已经解决了它。如果你解决了,请告诉我。(另外,我现在只是使用ArchLinux,没有任何问题。) - Star Brilliant
1
@rr- 我认为你应该把你的评论作为答案添加进去。我浪费了下午的时间来解决这个问题。 - jarnosz
我不知道为什么"-lstdc++"很重要,因为我猜想"-static-libstdc++"应该也有同样的效果。但是没有它,这个程序奇怪地无法运行。 - Daid Braam

27

您可能应该查看GCC的命令行选项文档。

没有“-static-something”命令,只能使用一个命令设置标准库(libgcc和libstdc++)进行静态链接。对于其他库,您需要先使用“-static”切换到静态链接,然后再使用单独的命令列出要包含的库,例如“-lpthread”。


我发现当我从我下载的mingw版本切换到Ubuntu上通过apt-get安装的版本时,这个问题出现了。虽然apt-get版本较旧,但我认为问题出现在使用不同配置构建mingw工具集上。添加“-static -lpthread”解决了这个问题。 - nmgeek
libgcc 不是标准库。请参见此处 - Paolo M
1
请告诉我如何使用-static选项,同时仍然使我的程序依赖于线程dll。 (我相当确定通过使用-static选项,您只需将所有内容链接为静态即可。在此之后您不需要再加入任何-l库。除非您能告诉我如何在此之后使其依赖于dll,否则这个答案是不正确的) - Puddle

26

即使程序中没有使用多线程,也可以通过向链接器传递 -Bstatic--whole-archive 参数来静态链接 winpthread

g++ -o hello.exe hello.cpp -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive

请注意以下内容:

  • 在此之后应立即禁用“整个存档”选项。
  • 如果您的程序实际上使用库中的符号(例如,您使用C++11中的<thread>),则无需执行此操作,这时静态链接将不会删除库文件。
  • 此操作旨在针对MinGW-w64,以解决libwinpthread-1.dll依赖问题。

1
这是一个很好的想法,但至少有一个缺点。主 exe 的 win32 资源被 libwinpthread-1.dll 的资源替换(使用文件浏览器查看 exe 属性;条目涉及 libwinpthread-1.dll 而不是 hello.exe)。 - Skywalker13
2
对我来说有效,只需要在--no-whole-archive旁边加上-Bdynamic,因为我没有一种方法将整个位追加到命令的最后(工具链的限制),而最终目标是共享库。 - feos

10

对于任何在CMake中工作的人,可以按照以下方式在您的CMakeLists.txt文件中轻松实现此解决方案...

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")

1
我只需在链接器标志 / LDFLAGS 中使用“-static”就能使它正常工作。 - Nathan Moinvaziri

7
显然,CMake在处理编译器标志-Wl时会出现一些奇怪的问题,使得解决方案-Wl,-Bstatic -lstdc++ -lwinpthread -Wl,-Bdynamic无法使用,似乎只剩下两个选项:不好的编译器标志-static和丑陋的编译器标志-Wl,--whole-archive
与此同时,在CMake中实际上有效的好方法似乎很少有文档记录,即直接使用链接器标志。因此,在CMake中,这似乎是将所有mingw-w64 C++依赖项静态链接的最佳方式:
target_link_libraries (MyVeryAwesomeApp -static gcc stdc++ winpthread -dynamic)

需要注意的是,即使没有显式使用-dynamic库,为了确保标准的隐式链接库能够正确链接,仍应该应用该选项。


“-static -dynamic” 将会静态链接所有内容,而在末尾加上 “-dynamic” 并没有任何作用。实际上,即使加上 -static -dynamicdgdf 也是可以的。我找不到关于 “-dynamic” 选项的文档,只有关于 “-static” 选项的文档。你所做的就是使用了不必要的额外选项,而只使用 -static 即可。事实上,不带 -static 后面的额外选项,生成的可执行文件大小更小。 - Puddle
@Puddle 如果在 -static 后省略额外选项时可执行文件更小,您能否解释一下这是如何发生的?如果像您所说的那样,这会使 gcc 静态链接所有内容?我认为,在尝试在没有安装 g++ 工具链、没有 gcc、stdc++ 和 winpthread dlls 的 Windows 实例上运行这样一个较小的可执行文件的实验,将会有很多收获。据我理解,在 target_link_libraries-static-dynamic 选项的作用与没有 CMake 的 -Bstatic-Bdynamic 的行为非常相似。 - S. Exchange Considered Harmful
谢谢。我在尝试为SDL2与OpenGL设置开发环境时遇到了这个问题。 - flamberge552
谢谢!由于某些原因,后面跟着“-dynamic”的COM库不再需要Wine导出,这太好了。 - Max Vlasov

1
我通过使用mingw工具链的win32版本而不是posix版本来解决了这个问题。使用win32版本,-static-libgcc -static-libstdc++足以进行独立构建。

你如何选择Win32变体? - ellipticaldoor
在Ubuntu上,mingw带有两个编译器i686-w64-mingw32-g++-posixi686-w64-mingw32-g++-win32。在我的构建环境中,我指定了CXX=/usr/bin/i686-w64-mingw32-g++-win32 - Hermann

0

如果您正在使用来自MSys2的工具链(已测试过gcc版本12),则使用winpthread静态方式的唯一方法是标准的-static(强制所有库都为静态)或者简单地删除/重命名libwinpthread.dll.a和libpthread.dll.a imp libs。 其他方法,如“Bstatic”、“-l:libwinpthread.a”将不再起作用(由于依赖关系问题,特别是在CMake中)。仍然可以使用整个存档文件的方法,但它会覆盖程序属性。 如果依赖关系来自于它们,您可能还需要静态链接libgcc和libstdc++。


-1
只需要链接 -l:libwinpthread.a

-2

只需将 -static 添加到你的 CFLAGS 中。

例如:./configure CFLAGS="-static"

这将把所有静态库链接到你的可执行文件中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接