I made some games with Visual C++ 2015 and OpenGL. When I ran it on my machine there was no problem, but when I ran it on other machines it shows that some DLLs are missing. I want to know how to make sure that it won't happen next time and what things should I consider so that I can avoid file missing problems?
-
8\$\begingroup\$ First, make sure you're building a Release version. \$\endgroup\$– Criticizing Israel not allowedCommented Mar 6, 2017 at 0:38
-
3\$\begingroup\$ If you want to be absolutely sure there are no dependencies from VS itself - but it comes with its own drawback - in the code generation settings you can choose to go with Multi Threaded / Multi Threaded Debug (for debug builds) instead of MT DLL / MT Debug DLL. It does increase your executable size and your binary compiled in this way won't benefit from the runtime dlls updates. But that's up to you. The plus side it that your executable won't have "external" dependencies. I won't post this as an answer because this is not a solution to your problem, just a workaround. \$\endgroup\$– GizmoCommented Mar 6, 2017 at 7:44
-
\$\begingroup\$ @Gizmo a workaround is still an answer and comments are temporary and used to clarify the posts they're under, and may be deleted. So if it's useful, you should post it as an answer. \$\endgroup\$– user1306322Commented Mar 7, 2017 at 6:04
-
\$\begingroup\$ Hm alright. I shall post it as an answer then. \$\endgroup\$– GizmoCommented Mar 7, 2017 at 8:15
5 Answers
You need to install the redistributables for the version of Visual Studio you used on any machine that wants to run the executables, e.g. https://www.microsoft.com/en-us/download/details.aspx?id=48145 for VS2015. You may also need redists for DirectX or other components.
Applications' installers generally install all the redistributables for any of their dependencies. You can make such an installer with InnoSetup, NSIS, WIX, or various other tools.
It's possible to make executables that don't need any redistributables, but you're then limited to a subset of core Windows functionality, which generally is not enough to make any kind of meaningful game or large application. The installers themselves are an example of applications that don't need any dependencies to run.
-
\$\begingroup\$ Is it possible to use VS to build such an installer? I thought I've seen something called OneClick in the project settings once. \$\endgroup\$ Commented Mar 7, 2017 at 5:50
-
\$\begingroup\$ @user1306322: absolutely, one solution was mentioned in the question's comments by Gizmo. It's just a matter of which runtimes/DLLs you link against. The default settings have you linking against the version-specific CRT DLL, but that can be changed by mucking in the linker options. Just link against
MSVCRT.DLL
(included with Windows itself) instead ofMSVCPxxx.DLL
(version-specific versions included with Visual Studio releases). \$\endgroup\$ Commented Mar 7, 2017 at 6:46 -
\$\begingroup\$ Or if you mean building a complete installer, that's basically what WIX is. It's a typical over-complicated XML-heavy Microsoft crapfest, but it works. There also used to be "installer projects" though I believe those are gone since 2013 or 2015. \$\endgroup\$ Commented Mar 7, 2017 at 6:50
I use Dependency Walker to track down missing DLL's:
Dependency Walker is also very useful for troubleshooting system errors related to loading and executing modules. Dependency Walker detects many common application problems such as missing modules, invalid modules, import/export mismatches, circular dependency errors, mismatched machine types of modules, and module initialization failures.
There is also a compile-time option in VS to statically link DLL's:
- Statically linking means the DLL's are included in the EXE file.
- Statically linking increases the size of the EXE file.
- Statically linking means this version of the DLL will always be used.
- However, statically linking also means you will never have a problem with missing DLL's.
-
1\$\begingroup\$ Dependency walker is quite old. It doesn't properly emulate Windows' mechanisms for loading DLLs anymore. Often leading to bogus messages about being unable to find DLLs. \$\endgroup\$– jpmc26Commented Mar 6, 2017 at 7:51
-
\$\begingroup\$ And statical linking may be forbidden in the license of a dependency. \$\endgroup\$ Commented Mar 6, 2017 at 20:38
For Visual C++, you have a few choices of how to handle the redistribution: run an EXE from your installer (with admin rights), use a MSM merge module with your MSI installer, or even side-by-side DLLs. See MSDN for the details.
The bigger issue is OpenGL. The only version of OpenGL that's included with Windows is a OpenGL 1.5 software renderer. Anything else requires a third party ICD to be installed.
This is one of the reasons why so many Windows games use DirectX instead since it's included with the operating system. See Direct3D 11 Deployment for Game Developers and Not So Direct Setup.
-
1\$\begingroup\$ The OpenGL advice is outdated - every modern graphics driver comes with an up-to-date OpenGL ICD. \$\endgroup\$ Commented Mar 6, 2017 at 0:38
-
\$\begingroup\$ Ive personally had to install openGL DLLs on machines as little as a year old \$\endgroup\$– GnemlockCommented Mar 6, 2017 at 4:30
-
\$\begingroup\$ @Gnemlock Immediately after reinstalling Windows on said year-old computer, you might be right. Did you continue to see this problem after installing the official driver package from NVIDIA, AMD, or Intel? \$\endgroup\$ Commented Mar 6, 2017 at 15:37
-
2\$\begingroup\$ @Gnemlock - if you are manually installing OpenGL DLLs then you're doing something horrificaly wrong. If you actually mean "install your GPU vendor's driver" then that's exactly what immibis just said too. \$\endgroup\$ Commented Mar 6, 2017 at 18:09
-
\$\begingroup\$ @Gnemlock - ah, so not relevant to the real world then. Thanks for clearing that up. \$\endgroup\$ Commented Mar 8, 2017 at 9:48
Disclaimer: This is a workaround, not a solution to your answer, but still, a very viable possibility.
If you want to be absolutely sure there are no dependencies from VS itself - but it comes with its own drawbacks - in the code generation settings you can choose to go with Multi Threaded (MT) / Multi Threaded Debug (MD) (for debug builds) instead of MT DLL (MTd) / MT Debug DLL (MDd).
What are the drawbacks?
- It does increase your executable size and your binary (although if you are making a game this is probably negligible)
- compiled in this way won't benefit from the runtime dlls updates. (e.g. if Microsoft releases VC++ 2015 SP2, SP3, SP4 etc..) But that's up to you.
- More RAM usage (also negligible) because you don't re-use existing/loaded code (DLLs)
- You need to be sure all libraries you link are compiled against the same runtime, else linking might fail, or interesting runtime errors might occur (probably not, but it did happen to me once in a lifetime in a legacy project that has been updated to the newest VS)
And what are the pros?
- your executable won't have "external" dependencies from VS itself (no msvc*.dll requirement).
- some people see this as a performance increase because you are eliminating DLL call overhead, while this is theoretically true, the improvements are negligible in practice
Check this link for a more elaborate explanation and for the pit- and downfalls you might encounter with using a static runtime.
Another workaround would be to put all the required DLL's where your binary is. Your application won't benefit from updates (to the runtime libraries) but that's it.
The real solution is to distribute the application in release/non debug dll mode (MTd) and supply the correct VC++ redistributable installer (and any other library installers that you might use, e.g. OpenAL, DirectX9, PhysX), and let the user run that before running your application (as other answers pointed out).
Also make sure to let the user know he/she possibly needs to update his/her GPU drivers (as those contain multiple runtimes for many applications too, e.g. OpenGL, Vulcan).
My solution was to copy and paste the DLL that caused the error into the folder where the .sln file is located in visual studio. After the #include
section, I wrote #pragma comment (lib, "lost DLL name with .dll")
and resolved it!
Note: I solved the problem that I encountered with a third party library (vulkan api) DLL. Maybe it's not known but 90% will work good luck :)