DLL Hell – How to include Microsoft redistributable runtime libraries in your CMake/CPack project

I recently ran across the following deployment problem on Windows.

On Windows clean machines other than the machine where I’m building the source, when I was trying to run my executable I was running in the infamous problem

On Windows XP:

The application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

On Windows 7:

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail.

This is due to the fact that you are not redistributing your msvc libraries with the executable, because you probably didn’t specify that you want to statically link them.

First temptative solution:

In CMake you have to specify to statically link the runtime libraries, by substituting in every occurrence the /MD option with /MT: this snippet can be of help, you simply have to put it in your CMakeLists.txt


foreach(flag_var
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
   if(${flag_var} MATCHES "/MD")
      string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
   endif(${flag_var} MATCHES "/MD")
endforeach(flag_var)

Also, this option has the downside of leaving /MD visible in the cache editor although it has no effect, so don’t worry.

This last solution is discussed in details here on the CMake website.

If after this modification you are still getting a bunch of linker errors in your project (probably because you are still linking to binary libraries which are not compiled with /MT option, like Qt ) then I warmly suggest you to change strategy rather than losing hours and hours on this issue.

My suggestion is to redistribute the runtime libraries with your executable and put them in the very same folder of the executable, so that the operating system can’t mess up with the libraries in C:\Windows\System32 and the libraries you are providing.

The solution comes from a CMake macro called InstalledRequiredSystemLibraries. I think that is present since version 2.8.4 in CMake, but remember to keep CMake up-to-date because many bugs are corrected in every version.

Case 1: You are not using OpenMP

If you are not dealing with OpenMP then you only have to use the following lines in your CMake script

include(InstallRequiredSystemLibraries)

The needed files to redistribute are contained in the variable

CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS

so you have to install as follows:

INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT Libraries)

Once you’ve generated your pack, try installing the program and the give a look at the folder where the executable lies. There should be also these files (I have Visual Studio 2008, also called msvc9, so the names of the libraries contain the 90, if you have VisualStudio2010, they have a 10)

msvcp90.dll msvcr90.dll msvcm90.dll

and a manifest file that indicates that you need those libraries.

In order to be sure that you will not get a “Side-by-side configuration incorrect” error, you have to check in some way that the executable contains the very same string contained in the manifest file. For example checking it with an editor like vim or emacs the occurence of the strings contained in the manifest file. Being more specific, this is a manifest file example:

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<!– Copyright (c) Microsoft Corporation.  All rights reserved. –>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
<noInheritable/>
<assemblyIdentity
type=”win32″
name=”Microsoft.VC90.CRT”
version=“9.0.21022.8”
processorArchitecture=”x86″
publicKeyToken=“1fc8b3b9a1e18e3b”
/>
<file name=”msvcr90.dll” /> <file name=”msvcp90.dll” /> <file name=”msvcm90.dll” />
</assembly>

Then within your editor you have to be sure that the very same strings are contained:If you’ve done correctly all these steps, then it’s hard that you will get the infamous error.

CASE 2: You are using OpenMP

In this case you are fighting against a bug in the InstallRequiredSystemLibraries CMake macro, because while the executable needs the OpenMP related library, he can’t find it. The library is

vcomp90.dll

in our case, because we are using VisualStudio 2008, and is not included in the CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS so the first solution is that you search for it in your computer and include it by brute-force in your project.

If you don’t know where to find that library, the CMake GUI can be of help. Try to search for the following string “REDIST_DIR” then you should come up with your REDISTRIBUTABLE directory where you can find the vcompXXX.dll  file.

So now you have to explicitly include the file in your package, these two lines do the work:


if (OPENMP_FOUND)
install(FILES "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.OPENMP/vcomp90.dll" DESTINATION bin COMPONENT Libraries)
install(FILES "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/redist/x86/Microsoft.VC90.OPENMP/Microsoft.VC90.OpenMP.manifest" DESTINATION bin COMPONENT Libraries)
endif(OPENMP_FOUND)

I hope this can help you to solve all your runtime libraries DLL hell problems.

Feel free to comment to discuss eventual problems.

Lascia un commento