Programming

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.

1 answer 1 view

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
<?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

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.LIB and /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:

  1. Right-click project → Properties → Vcpkg → set VcpkgTriplet to x64-windows-static.
  2. 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:

  1. Update all projects: Add <VcpkgTriplet>x64-windows-static</VcpkgTriplet> under <PropertyGroup Label="Vcpkg">.
  2. vcpkg.json tweak (in solution root): Add "vcpkgTriplet": "x64-windows-static" to manifest.
  3. Reintegrate Vcpkg: Run vcpkg integrate install if using legacy mode, but manifests are better.
  4. Clean everything: Delete all bin/obj, plus vcpkg installed/ cache.
  5. 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

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.

Authors
Verified by moderation
Moderation
Fix Vcpkg /MD vs /MT Runtime Mismatch in Visual Studio