64

I use mingw from here: 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

And I've sucessfully managed to link statically libstdc++-6.dll and libgcc_s_sjlj-1.dll by using -static-libgcc -static-libstdc++ parameters, but I cannot find a command for doing the same with libwinpthread-1.dll.

rsk82
  • 28,217
  • 50
  • 150
  • 240
  • 6
    Just for the sake of technical clarity, if you're statically linking, you're not linking to the DLL. The libraries `libgcc` and `libstdc++` have static and non-static (DLL) versions, and if you statically link, you're not linking to the DLLs. You want to statically link to the `pthreads` library, not to `libwinpthread-1.dll` (since you can't statically link to a dynamic library... that defeats the purpose of a dynamic library). – Cornstalks Dec 07 '12 at 18:36
  • I get: `c++: error: unrecognized command line option '-static-pthreads'` , the same with `winpthreads` – rsk82 Dec 07 '12 at 18:47
  • 2
    Quick gotcha: the libwinpthread-1.dll that comes with mingw is not the same as the one(s) floating round on the internet. Using the wrong one will result in an infinitely recursive DLL call (according to Dependency walker) followed by a stack overflow. – Mohan Mar 05 '18 at 10:21
  • Just link with `-l:libwinpthread.a` – superbem Feb 23 '21 at 19:07

10 Answers10

62

If your toolchain includes the static winpthreads, adding the option

-static

Will pull in static versions of all libraries it can.

Alternatively, you can remove libwinpthread.dll.a and the DLL itself from the toolchain directories. This might mess up programs linking with libstdc++ and libgcc DLLs though, so be careful.

A third option is to use -Wl,-Bdynamic and -Wl,-Bstatic to select which version you want linked in (which is what -static internally does when ld is called). An example:

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

If you run your link command with -v added, you should see these options appearing in the ld/collect2 invocation when you use -static-libgcc and -static-libstdc++.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
36

Try this:

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

Notice the -lstdc++ before -lpthread. It worked for me.

Make sure to add this to the very end of your g++ command line.

Star Brilliant
  • 2,916
  • 24
  • 32
  • 2
    This doesn't work for me, unfortunately, unless I remove the trailing `-Wl,-Bdynamic` (which is nonsense). – rr- Jun 16 '15 at 22:08
  • @rr- Try use gcc -v to print out verbose information, send it to me. And I will look into it. – Star Brilliant Jun 17 '15 at 06:15
  • 5
    I think I get it... I need `libwinpthread-1.dll` only if I compile with static `libstdc++`, meaning in my environment (arch and official repositories) static version of libstdc++ depends on shared winpthread. To get around this I probably need to compile mingw-w64 myself. – rr- Jun 18 '15 at 17:32
  • @rr- I am glad you have figured it out. Please tell me if you get it solved. (Also, I am just using ArchLinux now without any problem.) – Star Brilliant Jun 19 '15 at 18:38
  • 1
    @rr- I think you should add your comment as an answer. I wasted part of the afternoon figuring this out. – jarnosz Jan 18 '17 at 02:50
  • I don't know why the "-lstdc++" is important, as I would guess "-static-libstdc++" does the same. But without it, this doesn't work oddly enough. – Daid Braam Oct 03 '19 at 09:08
26

You should probably check command line options documentation for GCC.

These's no '-static-something' command, only standard libraries (libgcc and libstdc++) can be set to static linking with one command. For other libraries, you first switch to static linking with "-static" and then list the libraries to include with separate commands, ie "-lpthread".

Tomasz Lis
  • 292
  • 3
  • 2
  • I found that this problem surfaced when I switched from using a version of mingw I downloaded to the version installed by apt-get on Ubuntu. The apt-get version is older but I think the problem arises from a different configuration used to build the mingw tool set. Adding "-static -lpthread" fixed the problem. – nmgeek Jan 13 '16 at 18:31
  • `libgcc` is no standard library. See [here](https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html) – Paolo M Jul 27 '16 at 07:12
  • 1
    please tell me how i can use -static and then still make my program rely on the thread dll if you can. (i'm pretty sure by putting -static all you're doing is making it link everything static. you don't need to put anymore -l libraries after it. unless you can tell me how to make it rely on a dll afterwards, this answer is just incorrect) – Puddle Apr 10 '19 at 13:06
26

To statically link winpthread even if threading isn't used in the program, pass the -Bstatic and --whole-archive parameters to the linker:

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

Note the following:

  • The "whole archive" option should be disabled immediately afterwards.
  • You don't need to do this hack if your program actually uses symbols from the library (i.e. you use <thread> from C++11), in which case the library won't get dropped when you statically link it.
  • This hack is intended for MinGW-w64, to fix the libwinpthread-1.dll dependencies.
user7023624
  • 571
  • 5
  • 14
  • 1
    It's a great idea but there is at least one disadvantage. The win32 ressources of the main `exe` are replaced by the resources of `libwinpthread-1.dll` (look at the `exe` properties with the file explorer; the entries concern `libwinpthread-1.dll` instead of `hello.exe`). – Skywalker13 Aug 18 '18 at 22:53
  • 2
    Worked for me, just needed `-Bdynamic` alongside `--no-whole-archive`, because I don't have a way to append this whole bit to the very end of my command (limitations of the toolchain), and the end target is a shared lib. – feos Jun 01 '19 at 12:00
9

For anyone working in CMake, this solution is readily implemented in your CMakeLists.txt file as follows...

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
Syndog
  • 1,531
  • 4
  • 19
  • 27
6

Apparently, CMake does some weird stuff with how the -Wl compiler flags are handled, making the -Wl,-Bstatic -lstdc++ -lwinpthread -Wl,-Bdynamic solution not work, with only two other options seemingly left: the bad compiler flag -static and the ugly compiler flag -Wl,--whole-archive.

Meanwhile, the good option that actually works in CMake, yet seems rather undocumented, is to directly use the linker flags. Hence, in CMake, this seems to be the best way to statically link to all the mingw-w64 C++ dependencies:

target_link_libraries (MyVeryAwesomeApp -static gcc stdc++ winpthread -dynamic)

It should be noted that even if there isn't a library explicitly following -dynamic, it should still be applied in order to ensure that the standard, implicitly linked libraries get linked correctly.

  • `-static -dynamic` will statically link everything putting -dynamic at the end doesn't do anything. infact, putting `-static -dynamicdgdf` works. i can't find documentation on the `-dynamic` option only the `-static` option. all you're doing is `-static` with unneeded extras. without the extra options after `-static` the exe is actually smaller too – Puddle Apr 10 '19 at 12:18
  • @Puddle If the executable is smaller when missing the extra options after `-static`, care to explain as to how exactly that happens, if, as You claim, that makes gcc statically link everything? I think that an experiment involving an attempt to run such a smaller executable on a Windows instance that does not have the g++ toolchain installed, without the gcc, stdc++ and winpthread dlls in the same directory, would explain a lot. To my understanding, what the `-static` and `-dynamic` options do in `target_link_libraries` closely mirrors the behavior of `-Bstatic` and `-Bdynamic` without CMake. – S. Exchange Considered Harmful Apr 10 '19 at 16:42
  • Thanks I've been running into this issue when trying to set up a development environment for SDL2 with OpenGL. – flamberge552 Sep 20 '21 at 16:11
  • Thank you! For some reason, COM libraries followed by `-dynamic` do not require wine exports anymore, that's great. – Max Vlasov Aug 24 '22 at 08:55
1

I circumvented this problem by using win32 variant of the mingw toolchain instead of the posix variant. With the win32 variant, -static-libgcc -static-libstdc++ is sufficient for an independent build.

Hermann
  • 604
  • 7
  • 23
0

If you are using toolchains from MSys2 (tested with gcc version 12) ,the only way to use winpthread statically is standard -static (forces all library to be static) or simply delete/rename the libwinpthread.dll.a && libpthread.dll.a imp libs. Other methods like "Bstatic", "-l:libwinpthread.a" will no longer work (due to dependency hell, especially in CMake). The one with whole archive still works but it overrides the program properties. You may also want static link libgcc and libstdc++ if the dependency comes from them.

-1

Just link with -l:libwinpthread.a

superbem
  • 441
  • 3
  • 10
-2

Just add -static to your CFLAGS.

For example: ./configure CFLAGS="-static".

This will link all static libraries to your executable file.

trejder
  • 17,148
  • 27
  • 124
  • 216
Neobry
  • 13
  • 1