Many of the projects I’m working on seem to have wrong default properties in Debug configuration. For example, ‘Runtime Library’ is explicitly set to /MDd but defaults to /MD. ‘Basic Runtime Checks’ is explicitly set to /RTC1 but defaults to none. ‘Optimization’ is explicitly set to /Od but defaults to /O2, and so on:
This recently caused us some trouble, and the investigation results are dumped below.
The direct reason is that these vcxproj’s are missing the ‘UseDebugLibraries’ element, under the ‘Configuration’ PropertyGroup: it should be set to true in Debug and false in Release. A correct vcxproj should include some elements like –
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v120</PlatformToolset> <CharacterSet>Unicode</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <PlatformToolset>v120</PlatformToolset> <CharacterSet>Unicode</CharacterSet> </PropertyGroup>
Most ‘Configuration’ sub-elements (CharacterSet, ConfigurationType etc.) directly control import of custom property sheets, but UseDebugLibraries doesn’t. Instead, it is expected in various hooks around regular property sheets. For example, Microsoft.Cpp.mfcDynamic.props includes the following –
<ClCompile> <RuntimeLibrary Condition="'$(UseDebugLibraries)' != 'true'">MultiThreadedDll</RuntimeLibrary> <RuntimeLibrary Condition="'$(UseDebugLibraries)' == 'true'">MultiThreadedDebugDll</RuntimeLibrary> </ClCompile>
Why UseDebugLibraries was missing from some libraries and present in others remained a mystery until I noticed that the younger libraries tended to have this element. Indeed, the real culprit is the migration from VS2008- (vcproj format) to VS2010+ (vcxproj/MSBuild format). MS’s migration code just did not add this element. The generated projects are functional – they just explicitly set every individual compilation switch affected by UseDebugLibraries, which makes it overly verbose and a bit sensitive – especially in the presence of junior devs who tend to stick to defaults…
So every library you have which is 4Y+ old is susceptible to this migration bug, and I suggest you manually add UseDebugLibraries. If you have a central prop sheet where you can control multiple projects – add it there.
Not much point in reporting this to MS, is there? The chances of a fix are practically zero, and the issue would get equal web-presence here.
I just checked and that element is missing in some of our projects too. And sure enough, those were migrated from old projects. I’ve seen and wondered about the bold (ie. non-default) highlight on a few of those settings over the years. But since they were correct settings I didn’t investigate more deeply. Thanks Ofek!
Good to hear :)
Thanks for your article.
It was definitely relevant as certain items are not compatible between debug and release. These might be std::string and maybe even the exception management.
Thanks for your article.
Its relevant because a build mixed from debug and release items can fail badly on you.
Probably incompatible items between the two variants are std::string and exception handling.
Thank you for this.
I was having the same problem and still cannot find any other article on the internet describing it.
Does anyone know if there is a way to modify UseDebugLibraries from the GUI? I do not mind editing the file directly, but I am amazed that this item effects defaults but cannot be edited through visual studio. It seems to be an important distinction between release and debug configurations.
I tried creating a new blank project in Visual Studio 2017 and sure enough the release configuration has false while debug has true. I then tried creating a new empty configuration and that element was absent. It seems the only way to create a new configuration which has the value true is to select the debug configuration for the Copy Settings From option.
This really puzzles me. Does MS expect that the effect of having the wrong value for UseDebugLibraries will be trivial, or that all of us developers will find this obscurity?