How do I know which DLLs I need to include to properly build a project on windows using cmake and mingw?

I have a small C++17 program I wrote using a few SDL2 libraries. I created the project using Cmake, ninja, MSYS2, and MinGW. The exe I generate executes as expected when launching through a MSYS/mingw terminal. However launching the program outside of that terminal results in missing DLL errors (libwinpthread-1.dll, for example). Just as I need to include SDL2's DLLs, do I also need to include some MinGW DLLs if I want to distribute this to a system that doesn't have MinGW installed or added to the Path?

I am using a MSYS2/MinGW terminal to "mimic" a Linux terminal with a package manager. I run CMake to find the required packages and create a build script. Then I use Ninja to build the project, which at some point invokes MinGW's g++ port to compile the necessary files. Is this correct?


  • First, install ntldd using pacman -S ...-ntldd (e.g. pacman -S mingw-w64-x86_64-ntldd for the MINGW64 environment).

    Run ntldd -R my_program.exe (which is equivalent to ldd my_program on Linux).

    It will output a list of DLLs. Out of those DLLs:

    • Copy all DLLs in the list that are in your compiler's bin directory.
    • Copy DLLs of any libraries that you intentionally, manually linked.
    • Ignore the rest, such as DLLs in C:\Windows and in directories in PATH.

    It's also a good idea to check every DLL ignored in the third category, make sure that it doesn't also exist under a different path (one of the two first categories). If there is overlap, you need to re-run ntldd with offending directories removed from PATH (or, if there's stuff in C:\Windows, you need to either clear it up, or copy your DLLs right next to the .exe for them to have priority).

    This is usually not a problem if you run within MSYS2 shell, since it clears the PATH, unless you somehow installed custom DLLs to C:\Windows\**.

    Doing the same thing under Wine is quirky. It ships (sometimes?) its own OpenAL32.dll in its C:\Windows, which has priority over anything in PATH.

    So to get this procedure working reliably, I had to copy all my dependency DLLs next to the executable before running ntldd. Since I build OpenAL myself instead of installing from MSYS2, I opted to copy all self-built dependencies next to the .exe. If you instead install stuff from MSYS2, you'll probably need to temporarily copy every .dll in its bin directory instead.