VCLibs dependency incorrectly injected for Hybrid CRT self-contained apps via Microsoft.DesktopBridge.targets
Summary
When using the recommended "Hybrid CRT" approach for a self-contained Windows App SDK C++ desktop application, Microsoft.DesktopBridge.targets incorrectly injects VCLibs framework dependencies into the AppxManifest.xml during packaging, despite:
- Following the official self-contained deployment guide
- Setting
WinUISDKReferences=falseandWindowsAppSDKSelfContained=true - Not actually requiring VCLibs at runtime (Hybrid CRT statically links the CRT)
This phantom dependency causes CI validation failures when submitting to package repositories like winget-pkgs, blocking deployment despite the application being truly self-contained.
Impact
Real-world blocker: The FireDaemon Lozenge package PR was rejected by winget-pkgs automated validation due to this issue: https://github.com/microsoft/winget-pkgs/pull/294680#issuecomment-3307942555
The application runs perfectly without VCLibs installed, but CI tools flag it as having missing dependencies, requiring manual intervention to unblock PRs.
Environment
- Windows App SDK: 1.8.251003001
- Windows SDK Build Tools: 10.0.26100.6901
- CppWinRT: 2.0.250303.1
- Setup: Two-project solution (C++ .vcxproj + packaging .wapproj)
- CRT approach: Hybrid CRT (static linking, as recommended in HybridCRT.md)
The Problem
Despite correctly configuring the project for self-contained deployment, the final AppxManifest.xml contains:
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0"/>
<PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.33519.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"/>
<PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.33728.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"/>
</Dependencies>
Additionally, Microsoft.VCLibs.x64.14.00.Desktop.appx and Microsoft.VCLibs.x64.14.00.appx are copied to the bundle output folder.
Root cause: Microsoft.DesktopBridge.targets (specifically the _ResolveVCLibDependencies target) unconditionally determines there's a dependency on Microsoft.VCLibs.Desktop, Version=14.0 and injects it during packaging, ignoring project configuration.
Configuration Attempted
.vcxproj settings:
<PropertyGroup Label="Globals">
<AppContainerApplication>false</AppContainerApplication>
<AppxPackage>false</AppxPackage>
<ApplicationType>Windows Store</ApplicationType>
<UseWinUI>true</UseWinUI>
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<WinUISDKReferences>false</WinUISDKReferences>
<UseCrtSDKReferenceStaticWarning>false</UseCrtSDKReferenceStaticWarning>
</PropertyGroup>
<ItemGroup>
<SDKReference Remove="Microsoft.VCLibs.Desktop, Version=14.0" />
</ItemGroup>
.wapproj settings:
<PropertyGroup>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<WinUISDKReferences>false</WinUISDKReferences>
<IncludeGetResolvedSDKReferences>false</IncludeGetResolvedSDKReferences>
</PropertyGroup>
Package.appxmanifest (source):
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0" />
<!-- No PackageDependency elements - intentionally removed -->
</Dependencies>
None of these settings prevent the VCLibs injection during the packaging phase.
Expected Behavior
When using Hybrid CRT with WindowsAppSDKSelfContained=true and WinUISDKReferences=false:
- No VCLibs
PackageDependencyelements should appear in the final AppxManifest.xml - No VCLibs framework packages should be copied to the output folder
- The packaged app should validate as truly self-contained
Actual Behavior
Microsoft.DesktopBridge.targets ignores the project configuration and unconditionally:
- Adds VCLibs PackageDependency entries to AppxManifest.xml
- Copies VCLibs framework packages to the bundle output
- Creates a dependency that doesn't exist at runtime
Related Issues & Context
This appears to be a longstanding issue mentioned across multiple tickets:
Hybrid CRT related:
- #58 - Proposal: Address Project Reunion goals by addressing Visual Studio restrictions
- #1012 - Runtime install has missing dependency
- #2117 - Unable to release to the Microsoft Store (comment: https://github.com/microsoft/WindowsAppSDK/issues/2117#issuecomment-1043437985)
- #2143 - Proposal: remove requirement for CRT Redist if app is not using the CRT itself
- #2425 - Project templates should set
WinUISDKReferences=false - #4944 - Additional project properties when using the Hybrid CRT setup (comment: https://github.com/microsoft/WindowsAppSDK/issues/4944#issuecomment-3091967635)
Most relevant:
- #5799 - Enable tests in images that don't have the VCLibs available
- Comments: https://github.com/microsoft/WindowsAppSDK/issues/5799#issuecomment-3268458053
- https://github.com/microsoft/WindowsAppSDK/issues/5799#issuecomment-3278888777
- This issue directly mentions the same problem with
Microsoft.DesktopBridge.targets
Questions
- Is there a supported way to prevent
Microsoft.DesktopBridge.targetsfrom injecting VCLibs dependencies for Hybrid CRT apps? - Should the presence of
WindowsAppSDKSelfContained=trueandWinUISDKReferences=falsesignal to the Desktop Bridge targets that VCLibs injection should be skipped? - Is there an MSBuild property or target override that can properly disable this behavior?
Additional Context
The Hybrid CRT approach works flawlessly for deployment - the application runs perfectly without VCLibs installed. The issue is purely with the build/packaging tooling creating metadata that contradicts the actual runtime requirements, which breaks automated validation in distribution pipelines.
cc: @Scottj1s @alexlamtest (tagged based on #5799)
Workaround Request
If there's no immediate fix possible, guidance on a supported workaround would be appreciated. Manual manifest editing post-build is fragile and doesn't survive rebuilds.
@trueqbit Thanks for reporting. Yes this is a known limitation of using a Windows Application Packaging (WAP) project, which has no awareness of Windows App SDK settings. I'm not aware of any workaround other than using a single-project configuration. The only advantage of a WAP-based solution is to support multi-app ("multi-head") packages.
Honestly, if you are using the WAP based solution because the single project packaging doesn't fit your needs, it is often better to push forward and use a script to custom package.
The Visual Studio packaging projects have issues when you don't use a simple layout and I was running into missing libraries and other issues pretty regularly. Visual Studio does a lot of the work for you, for example, you don't have to worry about the application .pri generation, you only have to generate the package resources.pri. Also, because of the /f option, it is straight forward to generate the package layout from the build output.
Thanks @Scottj1s, @DarranRowe.
In my opinion, for reasons of separation of concerns, it is always desirable to separate the packaging project from the others.
Of course, I know nothing about the inner workings to understand why this cannot be corrected. Since everything is presented under the Microsoft banner, someone like me would naïvely assume that collaboration between the teams and their tool chains works smoothly. That's not to say that your work isn't appreciated :)
Since the use of the Hybrid CRT approach is recommended and desirable, it would be good to point out in large letters that this only works for a single project, but not for a WAP based solution. I didn't know that.
However, based on your feedback, I will switch to Advanced Installer as our current installation packaging tool, which will give me more control over the packaging process in the long run anyway.
Also feel free to convert this issue into a discussion, which might be more appropriate.