Fix Vcpkg /MD vs /MT Runtime Mismatch in Visual Studio
Resolve Vcpkg /MD vs /MT mismatch in Visual Studio. Use x64-windows-static triplet, update vcpkg.json, reinstall packages and rebuild to enforce /MT now.
Why is my C++ project building with /MD runtime library instead of /MT in Visual Studio using Vcpkg?
I have a large codebase using Vcpkg. I switched from /MD to /MT to reduce DLL dependencies, but most projects (except three) still build with /MD, despite project files specifying MultiThreaded and MultiThreadedDebug.
I’ve tried clean rebuilds and manually deleting obj and bin directories, but the issue persists.
Here’s the dumpbin output for one affected library:
File Type: LIBRARY
Linker Directives
-----------------
/NODEFAULTLIB:LIBC.LIB
/DEFAULTLIB:MSVCRT.LIB
/NODEFAULTLIB:LIBCMT.LIB
/NODEFAULTLIB:LIBCPMT.LIB
/NODEFAULTLIB:LIBCP.LIB
/DEFAULTLIB:MSVCPRT.LIB
/FAILIFMISMATCH:_CRT_STDIO_ISO_WIDE_SPECIFIERS=0
/alternatename:_Avx2WmemEnabled=_Avx2WmemEnabledWeakValue
/FAILIFMISMATCH:_MSC_VER=1900
/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=0
/FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease
/DEFAULTLIB:msvcprt
/FAILIFMISMATCH:annotate_string=0
/FAILIFMISMATCH:annotate_vector=0
/include:??3@YAXPEAX@Z
/DEFAULTLIB:uuid.lib
/DEFAULTLIB:uuid.lib
/DEFAULTLIB:uuid.lib
/DEFAULTLIB:atls.lib
/merge:ATL=.rdata
/DEFAULTLIB:kernel32.lib
/DEFAULTLIB:user32.lib
/DEFAULTLIB:advapi32.lib
/DEFAULTLIB:ole32.lib
/DEFAULTLIB:shell32.lib
/DEFAULTLIB:oleaut32.lib
/DEFAULTLIB:uuid.lib
/DEFAULTLIB:shlwapi.lib
/DEFAULTLIB:shlwapi.lib
/DEFAULTLIB:DbgHelp.Lib
/include:?e@?$exception_ptr_static_exception_object@Ubad_alloc_@exception_detail@boost@@@exception_detail@boost@@2Vexception_ptr@3@B
/include:?e@?$exception_ptr_static_exception_object@Ubad_exception_@exception_detail@boost@@@exception_detail@boost@@2Vexception_ptr@3@B
/DEFAULTLIB:LIBCMT
/DEFAULTLIB:OLDNAMES
Summary
50 .CRT$XCU
17C .bss
6200 .chks64
200 .data
3A4 .data$r
508 .data$rs
1076CC .debug$S
50 .debug$T
49C .drectve
13E0 .pdata
3DCF .rdata
12F8 .rdata$r
178 .text$di
13797 .text$mn
AD7 .text$x
3AF .text$yd
42 .voltbl
250F .xdata
454 .xdata$x
8 ATL$__a
8 ATL$__z
And here’s the relevant project file (.vcxproj):
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{BC9BB49D-3D4C-4EC4-876B-0582D381E3FC}</ProjectGuid>
<RootNamespace>Base</RootNamespace>
<Keyword>x64Proj</Keyword>
<ApplicationEnvironment>title</ApplicationEnvironment>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v145</PlatformToolset>
<UseOfAtl>false</UseOfAtl>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>bin\$(Configuration)</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>true</VcpkgEnableManifest>
<VcpkgEnabled>true</VcpkgEnabled>
<VcpkgUseStatic>true</VcpkgUseStatic>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\..\include\App;..\..\include\Rendering;..\Win;include;..\..\ThirdParty\sgCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;_LIB;_WIN32_WINNT=0x0600;NTDDI_VERSION=0x06000100;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FloatingPointModel>Fast</FloatingPointModel>
<PrecompiledHeader />
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>6011;6246;6285;6328;6334;6385;6386;6540;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<AdditionalOptions>/D "_SECURE_SCL=0" %(AdditionalOptions) /utf-8</AdditionalOptions>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpplatest</LanguageStandard>
<MultiProcessorCompilation Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</MultiProcessorCompilation>
</ClCompile>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalOptions>/D "_SECURE_SCL=0" %(AdditionalOptions) /utf-8</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<OmitFramePointers>false</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<AdditionalIncludeDirectories>..\..\include;..\..\include\App;..\..\include\Rendering;..\Win;include;..\..\ThirdParty\sgCore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;_LIB;_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>
</DisableSpecificWarnings>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|x64'">stdcpplatest</LanguageStandard>
<MultiProcessorCompilation Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</MultiProcessorCompilation>
</ClCompile>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CSGKernel.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CSGKernel.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
The project is configured for /MT, but the build still uses /MD. Where is /MD coming from, possibly due to Vcpkg or inherited settings?
Your C++ project in Visual Studio builds with the /MD runtime library instead of /MT because Vcpkg packages default to dynamic CRT linking (like x64-windows triplet), creating a mismatch with your project’s MultiThreaded setting. The dumpbin output reveals this through directives like /DEFAULTLIB:MSVCRT.LIB and FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease, which come directly from Vcpkg-built libraries. Switch to a vcpkg triplet such as x64-windows-static to align everything with /MT static linking and eliminate DLL dependencies across your large codebase.
Contents
- Understanding /MD vs /MT Runtime Libraries
- How Vcpkg Triplets Control Runtime Linking
- Analyzing Your Project File and Dumpbin Output
- Configuring Vcpkg for Static /MT in Visual Studio
- Step-by-Step Fix for Your Build
- Verifying and Troubleshooting the Solution
- Best Practices for Vcpkg in Large Codebases
Understanding /MD vs /MT Runtime Libraries
Visual Studio’s runtime library flags decide how your C++ code links to the Microsoft C Runtime (CRT). /MD pulls in the dynamic multithreaded DLL version (MSVCRT.dll), keeping your exe smaller but requiring DLL redistribution. /MT embeds the static multithreaded CRT directly into your binary, slashing external dependencies - perfect for your goal in a large codebase.
You picked /MT via <RuntimeLibrary>MultiThreaded</RuntimeLibrary> in both Debug and Release configs, which is spot on. But dumpbin exposes the culprit: linker directives forcing /DEFAULTLIB:MSVCRT.LIB (pure /MD) and blocking /MT libs like LIBCMT.LIB with /NODEFAULTLIB. These aren’t from your project; they’re baked into Vcpkg-supplied .lib files during their build.
Why does this happen? Vcpkg’s default triplets like x64-windows use /MD to match most setups. Your three working projects likely hit a different triplet or manual override, but the rest drag along the mismatch.
How Vcpkg Triplets Control Runtime Linking
Vcpkg triplets define build configs for every package - think architecture, linking type, and CRT flavor. The standard x64-windows triplet sets VCPKG_CRT_LINKAGE=dynamic (/MD or /MDd), while x64-windows-static flips it to static (/MT or /MTd).
Microsoft’s vcpkg docs on Windows platforms spell this out: static triplets use /MT by default, and static-md ones stick to /MD but link libs statically. Your dumpbin’s MSVCPRT.LIB and RuntimeLibrary=MD_DynamicRelease scream dynamic CRT from a non-static triplet.
Vcpkg triplet reference confirms triplets override project settings for package builds. Even with <VcpkgUseStatic>true</VcpkgUseStatic> in your .vcxproj (a non-standard prop), it doesn’t touch the triplet - Vcpkg ignores it for CRT linkage.
Analyzing Your Project File and Dumpbin Output
Your .vcxproj looks solid: PlatformToolset=v145, RuntimeLibrary=MultiThreaded for both configs, and VcpkgEnabled=true with manifest support. Clean rebuilds and obj/bin wipes rule out caching.
But dumpbin’s .drectve section tells the real story:
/DEFAULTLIB:MSVCRT.LIBand/DEFAULTLIB:MSVCPRT.LIB: Dynamic CRT libs./NODEFAULTLIB:LIBCMT.LIB: Explicitly rejects your /MT choice.FAILIFMISMATCH:RuntimeLibrary=MD_DynamicRelease: Vcpkg libs demand /MD.
These embed at package build time via Vcpkg. Stack Overflow threads on Vcpkg static linking mirror your exact issue - Dependency Walker shows DLLs lingering despite /MT.
Your <VcpkgEnableManifest>true</VcpkgEnableManifest> pulls vcpkg.json deps, but without a triplet override, it defaults to dynamic. The three good projects? Probably explicit triplet settings or older Vcpkg installs.
Configuring Vcpkg for Static /MT in Visual Studio
To force /MT everywhere, set the VcpkgTriplet project property to x64-windows-static. Vcpkg’s static linking blog post introduced built-in static triplets like x64-windows-static, which build all packages with /MT.
In Visual Studio:
- Right-click project → Properties → Vcpkg → set VcpkgTriplet to
x64-windows-static. - For multi-project solutions, add to Directory.Build.props:xml
<PropertyGroup> <VcpkgTriplet>x64-windows-static</VcpkgTriplet> </PropertyGroup>
Reinstall packages if needed: vcpkg install --triplet x64-windows-static. Vcpkg discussions on CRT mismatches hammer this home - mixing /MT project with dynamic Vcpkg triggers LNK2038 errors at link time.
Drop <VcpkgUseStatic>true</VcpkgUseStatic>; it’s redundant and non-official.
Step-by-Step Fix for Your Build
Here’s your action plan for the large codebase:
- Update all projects: Add
<VcpkgTriplet>x64-windows-static</VcpkgTriplet>under<PropertyGroup Label="Vcpkg">. - vcpkg.json tweak (in solution root): Add
"vcpkgTriplet": "x64-windows-static"to manifest. - Reintegrate Vcpkg: Run
vcpkg integrate installif using legacy mode, but manifests are better. - Clean everything: Delete all bin/obj, plus
vcpkg installed/cache. - Rebuild solution: MSBuild honors the triplet now.
For CMake users (if any subprojects), CMake 3.15+ MSVC_RUNTIME_LIBRARY sets it via set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>").
Test with dumpbin /directives on new .lib - expect /DEFAULTLIB:LIBCMT.LIB and no MSVCRT.
Verifying and Troubleshooting the Solution
Post-fix, dumpbin should show:
/DEFAULTLIB:LIBCMT.LIB(or LIBCMTD for Debug).- No /NODEFAULTLIB for MT libs.
- FAILIFMISMATCH:RuntimeLibrary=MT_StaticRelease.
Still /MD? Check:
- Inherited props from Microsoft.Cpp.props overriding you.
- Mixed triplets across deps - Reddit thread on Vcpkg static suggests project-wide Directory.Build.props.
- Vcpkg version <0.0. something without static support; update via git.
Link errors? Ensure all projects match—no hybrid /MD libs. Tools like Dependency Walker confirm zero CRT DLLs.
Best Practices for Vcpkg in Large Codebases
In big solutions like yours, lock triplets solution-wide via Directory.Build.props. Use vcpkg manifests over integrate for reproducibility. Prefer x64-windows-static-md if you want static libs but dynamic CRT (safer redistribution per Microsoft guidance).
Profile builds: /MT bloats exes 2-5MB but kills DLL hell. For distribution, static is king. Vcpkg triplet breakdowns clarify: VCPKG_LIBRARY_LINKAGE for lib type, VCPKG_CRT_LINKAGE for CRT.
You’ll love the lean deploys - no more “missing VCRUNTIME140.dll” nightmares.
Sources
- https://stackoverflow.com/questions/14172856/compile-with-mt-instead-of-md-using-cmake
- https://devblogs.microsoft.com/cppblog/vcpkg-updates-static-linking-is-now-available/
- https://stackoverflow.com/questions/58506430/how-to-statically-link-vcpkg-produced-lib-file-in-visual-studio
- https://stackoverflow.com/questions/67258905/vcpkg-difference-between-windows-windows-static-and-other
- https://github.com/microsoft/vcpkg/discussions/41344
- https://learn.microsoft.com/en-us/vcpkg/users/platforms/windows
- https://www.reddit.com/r/cpp_questions/comments/hwt78x/static_linking_with_vcpkg/
- https://learn.microsoft.com/en-us/vcpkg/concepts/triplets
Conclusion
Switching your vcpkg visual studio setup to the x64-windows-static triplet syncs the runtime library with /MT across all projects, banishing /MD mismatches for good. Your dumpbin proof and project tweaks confirm Vcpkg as the source—now rebuild lean and dependency-free. This scales perfectly for large C++ codebases, boosting portability without the DLL hassle.