Skip to content

Commit a45f702

Browse files
[build] make TrimMode=full function like NativeAOT (#22282)
Context: dotnet/android#8805 Context: dotnet/macios#20354 In .NET 9, we want .NET MAUI applications to be able to use the `TrimMode=full` option to remove unused code from the application: <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <TrimMode>full</TrimMode> </PropertyGroup> With all the trimming work done to support NativeAOT, we should toggle the same options when `TrimMode=full` is used: * `MauiStrictXamlCompilation=true` * `MauiXamlRuntimeParsingSupport=false` * `MauiShellSearchResultsRendererDisplayMemberNameSupported=false` * `MauiQueryPropertyAttributeSupport=false` * `MauiImplicitCastOperatorsUsageViaReflectionSupport=false` With these set, the `dotnet new maui` project template *should* have zero trimmer warnings when `TrimMode=full` is used. Developers can also adjust these settings and respond to trimmer warnings in their own code. I also updated `RunOnAndroid` and `RunOniOS` tests to verify that project templates launch successfully with `TrimMode=full`. Note: * Skip `maui-blazor` on iOS for now, as it contains trimmer warnings.
1 parent 837f579 commit a45f702

File tree

5 files changed

+51
-25
lines changed

5 files changed

+51
-25
lines changed

docs/design/FeatureSwitches.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Certain features of MAUI can be enabled or disabled using feature switches. The easiest way to control the features is by putting the corresponding MSBuild property into the app's project file. Disabling unnecessary features can help reducing the app size when combined with the [`full` trimming mode](https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options).
44

5+
The following switches are toggled for applications running on Mono for `TrimMode=full` as well as NativeAOT.
6+
57
| MSBuild Property Name | AppContext Setting | Description |
68
|-|-|-|
79
| MauiXamlRuntimeParsingSupport | Microsoft.Maui.RuntimeFeature.IsXamlRuntimeParsingSupported | When disabled, all XAML loading at runtime will throw an exception. This will affect usage of APIs such as the `LoadFromXaml` extension method. This feature can be safely turned off when all XAML resources are compiled using XamlC (see [XAML compilation](https://learn.microsoft.com/dotnet/maui/xaml/xamlc)). This feature is enabled by default for all configurations except for NativeAOT. |

src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
<_MauiXamlCValidateOnly Condition="'$(Configuration)' == 'Debug' AND '$(_MauiForceXamlCForDebug)' != 'True'">True</_MauiXamlCValidateOnly>
152152
<_MauiXamlCValidateOnly Condition="'$(BuildingForLiveUnitTesting)' == 'True' ">True</_MauiXamlCValidateOnly>
153153

154-
<MauiStrictXamlCompilation Condition="'$(MauiStrictXamlCompilation)' == '' and '$(PublishAot)' == 'true'">true</MauiStrictXamlCompilation>
154+
<MauiStrictXamlCompilation Condition="'$(MauiStrictXamlCompilation)' == '' and ('$(PublishAot)' == 'true' or '$(TrimMode)' == 'full')">true</MauiStrictXamlCompilation>
155155
<_MauiXamlCNoWarn>$(NoWarn)</_MauiXamlCNoWarn>
156156
<_MauiXamlCNoWarn Condition="'$(MauiStrictXamlCompilation)' != 'true'">$(_MauiXamlCNoWarn);XC0022;XC0023</_MauiXamlCNoWarn>
157157
</PropertyGroup>
@@ -212,11 +212,13 @@
212212

213213
<Target Name="_MauiPrepareForILLink" BeforeTargets="PrepareForILLink;_GenerateRuntimeConfigurationFilesInputCache">
214214
<PropertyGroup>
215-
<MauiXamlRuntimeParsingSupport Condition="'$(MauiXamlRuntimeParsingSupport)' == '' and '$(PublishAot)' == 'true'">false</MauiXamlRuntimeParsingSupport>
216215
<MauiEnableIVisualAssemblyScanning Condition="'$(MauiEnableIVisualAssemblyScanning)' == ''">false</MauiEnableIVisualAssemblyScanning>
217-
<MauiShellSearchResultsRendererDisplayMemberNameSupported Condition="'$(MauiShellSearchResultsRendererDisplayMemberNameSupported)' == '' and '$(PublishAot)' == 'true'">false</MauiShellSearchResultsRendererDisplayMemberNameSupported>
218-
<MauiQueryPropertyAttributeSupport Condition="'$(MauiQueryPropertyAttributeSupport)' == '' and '$(PublishAot)' == 'true'">false</MauiQueryPropertyAttributeSupport>
219-
<MauiImplicitCastOperatorsUsageViaReflectionSupport Condition="'$(MauiImplicitCastOperatorsUsageViaReflectionSupport)' == '' and '$(PublishAot)' == 'true'">false</MauiImplicitCastOperatorsUsageViaReflectionSupport>
216+
</PropertyGroup>
217+
<PropertyGroup Condition="'$(PublishAot)' == 'true' or '$(TrimMode)' == 'full'">
218+
<MauiXamlRuntimeParsingSupport Condition="'$(MauiXamlRuntimeParsingSupport)' == '' ">false</MauiXamlRuntimeParsingSupport>
219+
<MauiShellSearchResultsRendererDisplayMemberNameSupported Condition="'$(MauiShellSearchResultsRendererDisplayMemberNameSupported)' == ''">false</MauiShellSearchResultsRendererDisplayMemberNameSupported>
220+
<MauiQueryPropertyAttributeSupport Condition="'$(MauiQueryPropertyAttributeSupport)' == ''">false</MauiQueryPropertyAttributeSupport>
221+
<MauiImplicitCastOperatorsUsageViaReflectionSupport Condition="'$(MauiImplicitCastOperatorsUsageViaReflectionSupport)' == ''">false</MauiImplicitCastOperatorsUsageViaReflectionSupport>
220222
</PropertyGroup>
221223
<ItemGroup>
222224
<RuntimeHostConfigurationOption Include="Microsoft.Maui.RuntimeFeature.IsXamlRuntimeParsingSupported"

src/Controls/src/Core/StyleSheets/StylePropertyAttribute.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ sealed class StylePropertyAttribute : Attribute
1717
public bool Inherited { get; set; } = false;
1818

1919

20-
public StylePropertyAttribute(string cssPropertyName, Type targetType, string bindablePropertyName)
20+
public StylePropertyAttribute(
21+
string cssPropertyName,
22+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
23+
Type targetType,
24+
string bindablePropertyName)
2125
{
2226
CssPropertyName = cssPropertyName;
2327
BindablePropertyName = bindablePropertyName;

src/TestUtils/src/Microsoft.Maui.IntegrationTests/AndroidTemplateTests.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,31 @@ public void AndroidTemplateTearDown()
4747

4848

4949
[Test]
50-
[TestCase("maui", DotNetPrevious, "Debug")]
51-
[TestCase("maui", DotNetPrevious, "Release")]
52-
[TestCase("maui", DotNetCurrent, "Debug")]
53-
[TestCase("maui", DotNetCurrent, "Release")]
54-
[TestCase("maui-blazor", DotNetPrevious, "Debug")]
55-
[TestCase("maui-blazor", DotNetPrevious, "Release")]
56-
[TestCase("maui-blazor", DotNetCurrent, "Debug")]
57-
[TestCase("maui-blazor", DotNetCurrent, "Release")]
58-
public void RunOnAndroid(string id, string framework, string config)
50+
[TestCase("maui", DotNetPrevious, "Debug", null)]
51+
[TestCase("maui", DotNetPrevious, "Release", null)]
52+
[TestCase("maui", DotNetCurrent, "Debug", null)]
53+
[TestCase("maui", DotNetCurrent, "Release", null)]
54+
[TestCase("maui", DotNetCurrent, "Release", "full")]
55+
[TestCase("maui-blazor", DotNetPrevious, "Debug", null)]
56+
[TestCase("maui-blazor", DotNetPrevious, "Release", null)]
57+
[TestCase("maui-blazor", DotNetCurrent, "Debug", null)]
58+
[TestCase("maui-blazor", DotNetCurrent, "Release", null)]
59+
[TestCase("maui-blazor", DotNetCurrent, "Release", "full")]
60+
public void RunOnAndroid(string id, string framework, string config, string trimMode)
5961
{
6062
var projectDir = TestDirectory;
6163
var projectFile = Path.Combine(projectDir, $"{Path.GetFileName(projectDir)}.csproj");
6264

6365
Assert.IsTrue(DotnetInternal.New(id, projectDir, framework),
6466
$"Unable to create template {id}. Check test output for errors.");
6567

68+
var buildProps = BuildProps;
69+
if (!string.IsNullOrEmpty(trimMode))
70+
{
71+
buildProps.Add($"TrimMode={trimMode}");
72+
buildProps.Add("TrimmerSingleWarn=false");
73+
}
74+
6675
AddInstrumentation(projectDir);
6776

6877
Assert.IsTrue(DotnetInternal.Build(projectFile, config, target: "Install", framework: $"{framework}-android", properties: BuildProps),

src/TestUtils/src/Microsoft.Maui.IntegrationTests/AppleTemplateTests.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,19 @@ public void AppleTemplateFxtTearDown()
2525
}
2626

2727
[Test]
28-
[TestCase("maui", "Debug", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono)]
29-
[TestCase("maui", "Release", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono)]
30-
[TestCase("maui", "Debug", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono)]
31-
[TestCase("maui", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono)]
32-
[TestCase("maui-blazor", "Debug", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono)]
33-
[TestCase("maui-blazor", "Release", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono)]
34-
[TestCase("maui-blazor", "Debug", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono)]
35-
[TestCase("maui-blazor", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono)]
36-
[TestCase("maui", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.NativeAOT)]
37-
public void RunOniOS(string id, string config, string framework, string runtimeIdentifier, RuntimeVariant runtimeVariant)
28+
[TestCase("maui", "Debug", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono, null)]
29+
[TestCase("maui", "Release", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono, null)]
30+
[TestCase("maui", "Debug", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, null)]
31+
[TestCase("maui", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, null)]
32+
[TestCase("maui", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, "full")]
33+
[TestCase("maui-blazor", "Debug", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono, null)]
34+
[TestCase("maui-blazor", "Release", DotNetPrevious, "iossimulator-x64", RuntimeVariant.Mono, null)]
35+
[TestCase("maui-blazor", "Debug", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, null)]
36+
[TestCase("maui-blazor", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, null)]
37+
// FIXME: has trimmer warnings
38+
//[TestCase("maui-blazor", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.Mono, "full")]
39+
[TestCase("maui", "Release", DotNetCurrent, "iossimulator-x64", RuntimeVariant.NativeAOT, null)]
40+
public void RunOniOS(string id, string config, string framework, string runtimeIdentifier, RuntimeVariant runtimeVariant, string trimMode)
3841
{
3942
var projectDir = TestDirectory;
4043
var projectFile = Path.Combine(projectDir, $"{Path.GetFileName(projectDir)}.csproj");
@@ -52,6 +55,12 @@ public void RunOniOS(string id, string config, string framework, string runtimeI
5255
buildProps.Add("IlcTreatWarningsAsErrors=false"); // TODO: Remove this once all warnings are fixed https://github.com/dotnet/maui/issues/19397
5356
}
5457

58+
if (!string.IsNullOrEmpty(trimMode))
59+
{
60+
buildProps.Add($"TrimMode={trimMode}");
61+
buildProps.Add("TrimmerSingleWarn=false");
62+
}
63+
5564
Assert.IsTrue(DotnetInternal.Build(projectFile, config, framework: $"{framework}-ios", properties: buildProps),
5665
$"Project {Path.GetFileName(projectFile)} failed to build. Check test output/attachments for errors.");
5766

0 commit comments

Comments
 (0)