Skip to content

Commit

Permalink
[Trimming] Add ILC compilation test of all assemblies (#22328)
Browse files Browse the repository at this point in the history
* Fix effect registrar trimming warnings

* Fix StylePropertyAttribute trimming warning

* Fix DataTemplateExtension trimming warning

* Fix BindingExtension trimming warning

* Remove unnecessary Preserve attribute in NativeBindingService

* Add ILC test for all assemblies
  • Loading branch information
simonrozsival committed May 21, 2024
1 parent e5f53c0 commit 65c89dc
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 25 deletions.
1 change: 0 additions & 1 deletion src/Compatibility/Core/src/iOS/NativeBindingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
{
[Preserve(AllMembers = true)]
class NativeBindingService : INativeBindingService
{
[RequiresUnreferencedCode(TrimmerConstants.StringPathBindingWarning, Url = TrimmerConstants.ExpressionBasedBindingsDocsUrl)]
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core/Effect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ internal Effect()
public static Effect Resolve(string name)
{
Effect result = null;
if (Internals.Registrar.Effects.TryGetValue(name, out Type effectType))
if (Internals.Registrar.Effects.TryGetValue(name, out var effectType))
{
result = (Effect)DependencyResolver.ResolveOrCreate(effectType);
result = (Effect)DependencyResolver.ResolveOrCreate(effectType.Type);
}

if (result == null)
Expand Down
6 changes: 5 additions & 1 deletion src/Controls/src/Core/ExportEffectAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable disable
using System;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Maui.Controls
{
Expand All @@ -10,7 +11,9 @@ namespace Microsoft.Maui.Controls
public sealed class ExportEffectAttribute : Attribute
{
/// <include file="../../docs/Microsoft.Maui.Controls/ExportEffectAttribute.xml" path="//Member[@MemberName='.ctor']/Docs/*" />
public ExportEffectAttribute(Type effectType, string uniqueName)
public ExportEffectAttribute(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type effectType,
string uniqueName)
{
if (uniqueName.IndexOf(".", StringComparison.Ordinal) != -1)
throw new ArgumentException("uniqueName must not contain a .");
Expand All @@ -20,6 +23,7 @@ public ExportEffectAttribute(Type effectType, string uniqueName)

internal string Id { get; private set; }

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
internal Type Type { get; private set; }
}
}
21 changes: 18 additions & 3 deletions src/Controls/src/Core/Registrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,19 @@ static Registrar()
Registered = new Registrar<IRegisterable>();
}

internal static Dictionary<string, Type> Effects { get; } = new(StringComparer.Ordinal);
internal struct EffectType
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
public readonly Type Type;

public EffectType(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type)
{
Type = type;
}
}

internal static Dictionary<string, EffectType> Effects { get; } = new(StringComparer.Ordinal);

internal static Dictionary<string, IList<StylePropertyAttribute>> StyleProperties => LazyStyleProperties.Value;

Expand Down Expand Up @@ -394,9 +406,12 @@ public static void RegisterEffects(string resolutionName, ExportEffectAttribute[
}
}

public static void RegisterEffect(string resolutionName, string id, Type effectType)
public static void RegisterEffect(
string resolutionName,
string id,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type effectType)
{
Effects[resolutionName + "." + id] = effectType;
Effects[resolutionName + "." + id] = new(effectType);
}

/// <include file="../../docs/Microsoft.Maui.Controls.Internals/Registrar.xml" path="//Member[@MemberName='RegisterAll'][1]/Docs/*" />
Expand Down
27 changes: 16 additions & 11 deletions src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Maui.Controls.Internals;

namespace Microsoft.Maui.Controls.Xaml
Expand All @@ -21,18 +22,9 @@ public sealed class BindingExtension : IMarkupExtension<BindingBase>

BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
{
if (TypedBinding == null)
if (TypedBinding is null)
{
#pragma warning disable IL2026 // Using member 'Microsoft.Maui.Controls.Binding.Binding(String, BindingMode, IValueConverter, Object, String, Object)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Using bindings with string paths is not trim safe. Use expression-based binding instead.
// This code is only reachable in XamlC compiled code when there is a missing x:DataType and the binding could not be compiled.
// In that case, we produce a warning that the binding could not be compiled.
return new Binding(Path, Mode, Converter, ConverterParameter, StringFormat, Source)
{
UpdateSourceEventName = UpdateSourceEventName,
FallbackValue = FallbackValue,
TargetNullValue = TargetNullValue,
};
#pragma warning restore IL2026
return CreateBinding();
}

TypedBinding.Mode = Mode;
Expand All @@ -44,6 +36,19 @@ BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceP
TypedBinding.FallbackValue = FallbackValue;
TypedBinding.TargetNullValue = TargetNullValue;
return TypedBinding;

[UnconditionalSuppressMessage("TrimAnalysis", "IL2026",
Justification = "This code is only reachable in XamlC compiled code when there is a missing x:DataType and the binding could not be compiled. " +
"In that case, we produce a warning that the binding could not be compiled.")]
BindingBase CreateBinding()
{
return new Binding(Path, Mode, Converter, ConverterParameter, StringFormat, Source)
{
UpdateSourceEventName = UpdateSourceEventName,
FallbackValue = FallbackValue,
TargetNullValue = TargetNullValue,
};
}
}

object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Maui.Controls.Xaml
{
[ContentProperty(nameof(TypeName))]
[ProvideCompiled("Microsoft.Maui.Controls.Build.Tasks.DataTemplateExtension")]
[RequiresUnreferencedCode(TrimmerConstants.XamlRuntimeParsingNotSupportedWarning)]
public sealed class DataTemplateExtension : IMarkupExtension<DataTemplate>
{
public string TypeName { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void GetHandlerFromContainer()
public void GetEffectFromContainer()
{
string effectName = "anEffect";
Internals.Registrar.Effects[effectName] = typeof(MockEffect);
Internals.Registrar.Effects[effectName] = new Registrar.EffectType(typeof(MockEffect));
var effect = new MockEffect();
_container.Register(typeof(MockEffect), effect);
var result = Effect.Resolve(effectName);
Expand Down
68 changes: 62 additions & 6 deletions src/TestUtils/src/Microsoft.Maui.IntegrationTests/TemplateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,57 @@ public void PublishNativeAOT(string id, string framework, string runtimeIdentifi
Assert.IsTrue(DotnetInternal.New(id, projectDir, DotNetCurrent),
$"Unable to create template {id}. Check test output for errors.");

var extendedBuildProps = BuildProps;
extendedBuildProps.Add("PublishAot=true");
extendedBuildProps.Add("PublishAotUsingRuntimePack=true"); // TODO: This parameter will become obsolete https://github.com/dotnet/runtime/issues/87060 in net9
extendedBuildProps.Add("_IsPublishing=true"); // This makes 'dotnet build -r iossimulator-x64' equivalent to 'dotnet publish -r iossimulator-x64'
extendedBuildProps.Add("IlcTreatWarningsAsErrors=false");
extendedBuildProps.Add("TrimmerSingleWarn=false");
var extendedBuildProps = PrepareNativeAotBuildProps();

string binLogFilePath = $"publish-{DateTime.UtcNow.ToFileTimeUtc()}.binlog";
Assert.IsTrue(DotnetInternal.Build(projectFile, "Release", framework: framework, properties: extendedBuildProps, runtimeIdentifier: runtimeIdentifier, binlogPath: binLogFilePath),
$"Project {Path.GetFileName(projectFile)} failed to build. Check test output/attachments for errors.");

var actualWarnings = BuildWarningsUtilities.ReadNativeAOTWarningsFromBinLog(binLogFilePath);
actualWarnings.AssertNoWarnings();
}

[Test]
[TestCase("maui", $"{DotNetCurrent}-ios", "ios-arm64")]
[TestCase("maui", $"{DotNetCurrent}-ios", "iossimulator-arm64")]
[TestCase("maui", $"{DotNetCurrent}-ios", "iossimulator-x64")]
[TestCase("maui", $"{DotNetCurrent}-maccatalyst", "maccatalyst-arm64")]
[TestCase("maui", $"{DotNetCurrent}-maccatalyst", "maccatalyst-x64")]
public void PublishNativeAOTRootAllMauiAssemblies(string id, string framework, string runtimeIdentifier)
{
// This test follows the following guide: https://devblogs.microsoft.com/dotnet/creating-aot-compatible-libraries/#publishing-a-test-application-for-aot
if (!TestEnvironment.IsMacOS)
Assert.Ignore("Publishing a MAUI iOS app with NativeAOT is only supported on a host MacOS system.");

var projectDir = TestDirectory;
var projectFile = Path.Combine(projectDir, $"{Path.GetFileName(projectDir)}.csproj");

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

var extendedBuildProps = PrepareNativeAotBuildProps();
FileUtilities.ReplaceInFile(projectFile,
"</Project>",
"""
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls.Foldable" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Controls.Maps" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Maui.Graphics.Skia" Version="$(MauiVersion)" />
</ItemGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Microsoft.Maui" />
<TrimmerRootAssembly Include="Microsoft.Maui.Controls" />
<TrimmerRootAssembly Include="Microsoft.Maui.Controls.Compatibility" />
<TrimmerRootAssembly Include="Microsoft.Maui.Controls.Foldable" />
<TrimmerRootAssembly Include="Microsoft.Maui.Controls.Maps" />
<TrimmerRootAssembly Include="Microsoft.Maui.Controls.Xaml" />
<TrimmerRootAssembly Include="Microsoft.Maui.Essentials" />
<TrimmerRootAssembly Include="Microsoft.Maui.Graphics" />
<TrimmerRootAssembly Include="Microsoft.Maui.Graphics.Skia" />
<TrimmerRootAssembly Include="Microsoft.Maui.Maps" />
</ItemGroup>
</Project>
""");

string binLogFilePath = $"publish-{DateTime.UtcNow.ToFileTimeUtc()}.binlog";
Assert.IsTrue(DotnetInternal.Build(projectFile, "Release", framework: framework, properties: extendedBuildProps, runtimeIdentifier: runtimeIdentifier, binlogPath: binLogFilePath),
Expand All @@ -297,6 +342,17 @@ public void PublishNativeAOT(string id, string framework, string runtimeIdentifi
actualWarnings.AssertNoWarnings();
}

private List<string> PrepareNativeAotBuildProps()
{
var extendedBuildProps = new List<string>(BuildProps);
extendedBuildProps.Add("PublishAot=true");
extendedBuildProps.Add("PublishAotUsingRuntimePack=true"); // TODO: This parameter will become obsolete https://github.com/dotnet/runtime/issues/87060 in net9
extendedBuildProps.Add("_IsPublishing=true"); // This makes 'dotnet build -r iossimulator-x64' equivalent to 'dotnet publish -r iossimulator-x64'
extendedBuildProps.Add("IlcTreatWarningsAsErrors=false");
extendedBuildProps.Add("TrimmerSingleWarn=false");
return extendedBuildProps;
}

[Test]
[TestCase("maui", DotNetCurrent, "Release")]
public void PublishUnpackaged(string id, string framework, string config)
Expand Down

0 comments on commit 65c89dc

Please sign in to comment.