CsWinRT
CsWinRT copied to clipboard
Support IL Trimming for projection assemblies
Proposal: Support for trimmable (ILLink) assemblies
Summary
Trimming is a great feature introduced with .NET 5, but CsWinRT does not yet support it. This should be fixed, so assembly sizes can be reduced.
Rationale
Trimming with ILLink provides great results when publishing self contained applications. I have reduced the size of the Microsoft.Windows.SDK.NET assembly by a factor of 45
, taking it from 25mb to 0.55mb! I see the same great result in other projected libraries as well.
Since WinUI is using CoreCLR, trimming will be an important tool to keep assemblies small. Same goes for Xamarin apps using the desktop SDK.
Important Notes
Issues encountered so far:
- Internal constructors, used by internal factories, are incorrectly trimmed.
- Missing interfaces and types in the ABI namespace. Perhaps an explicit interface implementation could fix this.
As you can expect, the reflection-based factories in the ABI namespace quickly break, however, these types can manually be preserved by whitelisting them using a TrimmerRootDescriptor
.
ILLink can be enabled by specifying the following properties:
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
To whitelist the Windows SDK for trimming:
<ItemGroup>
<ManagedAssemblyToLink Condition="'%(Filename)' == 'Microsoft.Windows.SDK.NET'">
<IsTrimmable>true</IsTrimmable>
</ManagedAssemblyToLink>
</ItemGroup>
Further reading: https://github.com/mono/linker/blob/main/docs/data-formats.md
C#/Win32 ask for C#/WinRT (.NET 6 timeframe) - IL Trimming could remove baggage from the TFM.
cc @mikebattista
Thanks Angela. As we integrate more support in the TFMs for things like C#/Win32, we don't want apps to then have to carry around baggage for things they may not even be using. Pay for play is definitely the right model here, so leveraging assembly trimming for that would benefit C#/WinRT customers as well as C#/Win32 customers. It would be a great story to say that setting your TFM gets you access to all Windows APIs without any baggage. You only pay for what you use.
After speaking with the IL linker team, it looks like there's a few things we'll need:
- Reference and look up ABI.* and ABI.Impl.* types via attributes instead of using Type.GetType (we'll need to keep Type.GetType as a fallback for back-compat)
- Annotate the generated code and WinRT.Runtime with linker dataflow annotations and warning suppressions as needed. CsWinRT needs to be careful to manually propagate the linker annotations on methods and types called via reflection with MakeGenericType and MakeGenericMethod so the annotations don't get lost in the process.
Hi all,
Has there been updates on this effort? With. NET 6 coming out next week and especially the focus on NativeAOT in .NET 7, the lack of IL Trimming means that those migrating away from. NET Native and UWP will have to deal with larger binaries.
@snickler - This is a priority for the C#/WinRT team. It is penciled in for spring 2022, but we are doing another planning review before then, so things may change.
Please continue to target .NET 6.0 with your efforts as that is now LTS.
I am hoping this is coming soon, because a small 700KB WinForms app, was bloated to a 60MB WindowsAppADK app.
@angelazhangmsft any updates of progress or current roadmap?
I also find that IL Trimming should have more development, since IL Trimming in NativeAOT is a requirement. My project depends on whether this will or won't be supported. Right now I am limited to a very small amount of APIs.
WinUI3 is also very dependend on that so it would be highly appreciated if there was more development regarding that issue.
There's been good progress on the C#/WinRT front. @manodasanW can comment on that.
That sounds great ^^
With CsWinRT 2.0, IL trimming is now supported. The Windows SDK projection has been updated to use that version and mark it as trimmable which is available in .NET SDK 6.0.109, 6.0.304 or 6.0.401 or later. Similarly, WinAppSDK 1.2 preview 2 has also been updated to use that CsWinRT version and mark its C#/WinRT projection assemblies trimmable.
Application on those versions can enable PublishedTrimmed in their publish profile and see improvements to their app's disk footprint. You should make sure to thoroughly test your application with trimming enabled to ensure any necessary types didn't get trimmed or result in a change in behaviour.
Seems that it still doesn't work. We are getting 0xc000027b in Microsoft.UI.Xaml.dll after enabling trimming (TrimMode=link).
@hez2010 0xc000027b indicates a stowed exception and we will need to figure out what the actual exception was. Have you been able to run your trimmed app under a debugger and see if you see any exceptions thrown and get the stacks for them? That should help figure out where the issue is.
I first encountered "failure to parse XAML", but it turned out to be the CommunityToolkit isn't compatible with trimming. After rooting all CommunityToolkit assemblies, I encountered 0xc0000005 due to "class is not registered":
onecore\com\combase\objact\objact.cxx(4070)\combase.dll!00007FFBAAFE5175: (caller: 00007FFBAAFECEBA) ReturnHr(7) tid(44bc) 80040154 クラスが登録されていません
(7638.2018): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
windows_storage!CShellLibrary::_GetFirstMatchingFolder+0x49:
00007ffb`a745d089 488b4008 mov rax,qword ptr [rax+8] ds:00000000`00000008=????????????????
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
Unable to read dynamic function table entries
The exception happened at https://dev.azure.com/microsoft/OS/_apis/git/repositories/os.2020/items?path=/onecore/com/combase/objact/objact.cxx&versionDescriptor.versionType=commit&versionDescriptor.version=791ab59ca0476c59ad47a3cb5e6f0730e26425ba&versionDescriptor.options=none&download=true&api-version=2.0, but apparently I don't have any access to Microsoft internal code.
Stacktrace:
It may not be caused by WinAppSDK/CsWinRT (because we are also using COM interop). Will post an update if I have further information.