Compiling static or dynamic libraries in my game with mingw.

I am wanting to learn a little more about compiling libraries into my game, some dynamically, some statically. And what I should expect along the way. I am hoping to document this for others compiling games using mingw (with gmake, codelite or clock::blocks).

The issue

When running my mingw compiled game, I receive the following errors when removing the path to my C:\MinGW-6.3.0\bin folder:

The program can't start because libstdc++6.dll is missing from your computer. Try reinstalling the program to fix this problem.

The program can't start because libgcc_s_dw2-1.dll is missing from your computer. Try reinstalling the program to fix this problem.

My game structure

My current game file structure is laid out something like this:

bin/
Output.exe <- release build of the game
orx.dll <= game framework dll

data/ <- folder containing my assets
src/ <- containing around 10 .cpp and .h files.

The ideal situation

I would like to end up with:

  • Data folder with my assets
  • Bin folder with:
    • my game .exe which has libstdc++6.dll and libgcc_s_dw2-1.dll statically linked.
    • The orx.dll which the .exe dynamically links to.

There's a number of references to this issue via various searches. The easiest fix is to simply copy libstdc++6.dll and libgcc_s_dw2-1.dll next to my .exe, but I wish to have the configuration above, having them statically compiled in.

Experimenting and Learning

First I took note the the sizes of the various libraries:

libgcc_s_dw2-1.dll 917K
libstdc++-6.dll 1474K
orx.dll 6703K

My executable, which dynamically links to orx.dll is: 513K

I have read that by adding -static to the linker options in my makefile (ALL_LDFLAGS) should statically compile in the libraries to my exe. So by doing so and compiling again, the second compile is slightly larger. The two exe's are:

Outpost-dynamic.exe 513K
Outpost-static.exe 748K

The difference between the static and dynamic version is 235K. None of my libraries above are around that size, so I am not sure what compiled in statically.

If I test either of these .exe's they will fail looking for the libstdc++6.dll and libgcc_s_dw2-1.dll again.

The static version prompts for the files once, the dynamic one prompts for them twice.

I then inspected both exe's in Dependency Walker. I am not 100% of how to interpret the results, but I'll have a go, please tell me if I am wrong. Firstly, the regular dynamic version:

Interesting that it shows orx.dll because (while not compiled into the exe) it is a dependency, and therefore will be loaded during execution. Also, the exe know it needs libstdc++6.dll and libgcc_s_dw2-1.dll, but because I took the path away, the exe will not work.

Next I try the static one:

Even more interesting. libstdc++6.dll and libgcc_s_dw2-1.dll no longer show. Probably because they are statically compiled in? But I can't find any trace of them. But the exe is not looking for them anymore. (That's a lie, because the orx.dll if expanded is still looking for them).

The next thing to try is to add the entire static compile linker flags: -static -static-libgcc -static-libstdc++

However, after cleaning and compiling again, the result is an exe that is 748K again. So perhaps those flags are in the wrong place.

I have also tried combinations of -Wl flags to set some things dynamic and some static, but I might not have gotten it right.

Conclusion

I really want to understand what I should expect by trying to compile things statically. Should the files have compiled into my exe? Did it actually succeed? Did I miss some other required step? Why did they file sizes differ? Was there some success in doing this?

Tagged:

Comments

  • I'll be working on modifying premake to add static linking support for gcc/clang/mingw and will let you know how it goes.

  • Thanks @iarwain

    Do you have any comments about how I went about trying to compile statically. Were my expectations correct about the file sizes and what I expected to see.?

  • Ah right. So yes adding static will link the defined dependencies directly inside your binary file.

    That's why they don't show up in Dependency Walker anymore (which only shows dependencies, not things that are included inside the binary itself, including static libraries as they're now part of the binary itself).

    The difference of size is expected, you're probably not using everything from those libraries and only the relevant stuff should make it inside the compiled binaries.

    Lastly, you still get the error message about the missing DLLs as you need to statically link both orx.dll and your game executable otherwise one of these two will still be looking for them as external dependencies (DLLs).

  • So the link can intelligently see what code is actually used by the binary and only statically compile in the routines as it needs? That's clever. I assumed statically compiling in a library was an all or nothing affair.

    Also, is it not possible for me to say that I want to statically compile the two other libs to my binary but have the orx.dll dynamically compile? That way, I would imagine those two libs would not be prompted for anymore. The binary would provide them, and orx.dll would be provided to the binary.

  • I'd have to verify it, but it's very possible the mix of statically linked and dynamically linked libraries is not going to work as the symbols might have different names. Though maybe I'm wrong so we'd need to test it. :)

  • Also, after thinking a bit about it, I don't think the DLL would know anything about the symbols that are in the executable, so it'll likely look for the two external DLLs as well.

  • @sausage I've updated the Windows version of premake if you want to give it a try (just need to sync orx's repo and build with MinGW). I haven't tried with CodeLite/Code::Blocks either.

Sign In or Register to comment.