Skip to content

Enable PublishTrimmed for Release builds #21

@hoobio

Description

@hoobio

Problem

The Release publish currently runs with <PublishTrimmed>False</PublishTrimmed>. Enabling trimming would shrink the self-contained payload by an expected 30-50% on top of the wins already shipped in PR #19, taking the MSI down to roughly 30-40 MB (the bitwarden Command Palette reference produces a 20 MB MSI for a comparable WinUI 3 app shape).

Attempted this in PR #19 and reverted: with PublishTrimmed=true and TrimMode=partial, the .NET 10 trimmer hard-strips System.StubHelpers.InterfaceMarshaler (and friends) when classic-COM interop is reachable, even with:

  • <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
  • <RuntimeHostConfigurationOption Include=\"System.Runtime.InteropServices.BuiltInComInterop.IsSupported\" Value=\"true\" Trim=\"false\" />
  • An explicit TrimmerRootDescriptor rooting System.StubHelpers.InterfaceMarshaler, StubHelpers, MngdRefCustomMarshaler, etc., plus NAudio.Core, NAudio.Wasapi, and Earmark.Audio.

The trimmer prints IL2026: Built-in COM support is not trim compatible (https://aka.ms/dotnet-illink/com), and the runtime then throws TypeLoadException: Could not load type 'System.StubHelpers.InterfaceMarshaler' on the first MMDeviceEnumerator constructor call.

Proposed Solution

Land #22 (own classic-COM interop) and #23 (NAudio.CoreAudioApi side) first, then re-enable trimming:

  1. Set <PublishTrimmed>true</PublishTrimmed> and <TrimMode>partial</TrimMode> in src/Earmark.App/Earmark.App.csproj.
  2. Turn on <EnableTrimAnalyzer>true</EnableTrimAnalyzer> and fix any IL2026/IL2072 warnings in our own code (the JSON path is already trim-safe via the JsonSerializerContext pair landed in perf(installer): shrink MSI size #19; expect a small handful of additional sites).
  3. Set <ILLinkTreatWarningsAsErrors>false</ILLinkTreatWarningsAsErrors> so the rolled-up library trim warnings (CsWinRT, .NET WinRT projection, System.Drawing.Common rollup via System.Private.Windows.Core) don't block the build.
  4. Validate the trimmed publish:
    • No new IL2xxx warnings on our code at build time.
    • App launches from the MSI install dir, parks in the tray, surfaces the main window via secondary activation.
    • Log shows Audio services initialized, Activated factory ... as Win11 layout, and Applied rule ... lines, i.e. the COM paths still execute.
  5. Update CLAUDE.md ## Build, run, and iterate so the inner-loop publish command no longer carries the trimming-disabled caveat.

Alternatives Considered

  • Workarounds with the existing classic-COM code. Tried BuiltInComInteropSupport=true, the Trim=\"false\" host configuration option, and a TrimmerRootDescriptor covering System.Private.CoreLib's System.StubHelpers.* types and entire-assembly preserves for NAudio.Core / NAudio.Wasapi / Earmark.Audio. None worked: see PR perf(installer): shrink MSI size #19's reverted commits for the full sequence. Microsoft's official guidance at https://aka.ms/dotnet-illink/com is to migrate to ComWrappers.
  • Native AOT instead of trimmed self-contained. WinUI 3 unpackaged + Native AOT is not yet supported by Microsoft.WindowsAppSDK 1.8 in a way Earmark could ship. Re-evaluate when WAS adds first-class AOT support.

Additional Context

Checklist

  • I searched existing issues and this hasn't been requested yet

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions