Browse Source

New pass of AOT warning fixes (#21616)

* Use CompiledBinding.Create where possible in sample code

* Avoid "FullyQualifiedName" hacks, use AppContext.BaseDirectory

* Avoid ambigious binding to methods in the sample code

* Use ProcessPath, there are no "dll" in aot

* Disable devtools in release

* Remove "DefineDynamicAssembly" used for persistent assemblies output, we don't target net framework anymore

* Add RequiresDynamicCode to the runtime XAML loader

* Bump XAML

* Bump XAML
pull/21624/head
Max Katz 4 months ago
committed by GitHub
parent
commit
573849844a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      Directory.Packages.props
  2. 2
      build/SampleApp.props
  3. 2
      external/XamlX
  4. 2
      samples/AppWithoutLifetime/Program.cs
  5. 2
      samples/BindingDemo/App.xaml.cs
  6. 7
      samples/ControlCatalog.Desktop/NativeControls/Gtk/EmbedSample.Gtk.cs
  7. 2
      samples/ControlCatalog.Desktop/Program.cs
  8. 4
      samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs
  9. 3
      samples/ControlCatalog/Pages/CarouselPage/CareCompanionAppPage.xaml.cs
  10. 7
      samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
  11. 6
      samples/ControlCatalog/Pages/NotificationsPage.xaml
  12. 10
      samples/ControlCatalog/Pages/NotificationsPage.xaml.cs
  13. 2
      samples/GpuInterop/Program.cs
  14. 2
      samples/IntegrationTestApp/Program.cs
  15. 4
      samples/RenderDemo/App.xaml.cs
  16. 2
      samples/SafeAreaDemo.Desktop/Program.cs
  17. 2
      samples/Sandbox/Program.cs
  18. 2
      samples/TextTestApp/Program.cs
  19. 2
      samples/VirtualizationDemo/Program.cs
  20. 18
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
  21. 85
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

2
Directory.Packages.props

@ -7,7 +7,7 @@
<PackageVersion Include="Appium.WebDriver" Version="5.2.0" />
<PackageVersion Include="Avalonia.Angle.Windows.Natives" Version="2.1.27548.20260419" />
<PackageVersion Include="Avalonia.BuildServices" Version="11.3.2" />
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.1" />
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.2" />
<PackageVersion Include="BenchmarkDotNet" Version="0.15.6" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Dotnet.Bundle" Version="0.9.13" />

2
build/SampleApp.props

@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" />
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Condition="'$(Configuration)' == 'Debug'" />
</ItemGroup>
<Target Name="GatherReferences" AfterTargets="CoreCompile">

2
external/XamlX

@ -1 +1 @@
Subproject commit 86f5a26fadb745e95169c3c805ebd9fd7c9b44d2
Subproject commit d7e37ca63dc9b13cdc95ca165938d4904fa0eddf

2
samples/AppWithoutLifetime/Program.cs

@ -24,6 +24,8 @@ class Program
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}

2
samples/BindingDemo/App.xaml.cs

@ -24,7 +24,9 @@ namespace BindingDemo
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}
}

7
samples/ControlCatalog.Desktop/NativeControls/Gtk/EmbedSample.Gtk.cs

@ -21,10 +21,11 @@ public class EmbedSampleGtk : INativeDemoControl
}
var control = createDefault();
var nodes = Path.GetFullPath(Path.Combine(typeof(EmbedSample).Assembly.GetModules()[0].FullyQualifiedName,
"..", "NativeControls", "Gtk", "nodes.mp4"));
var nodesFile = Path.Combine(AppContext.BaseDirectory, "NativeControls", "Gtk", "nodes.mp4");
nodesFile = Path.GetFullPath(nodesFile);
_mplayer = Process.Start(new ProcessStartInfo("mplayer",
$"-vo x11 -zoom -loop 0 -wid {control.Handle.ToInt64()} \"{nodes}\"")
$"-vo x11 -zoom -loop 0 -wid {control.Handle.ToInt64()} \"{nodesFile}\"")
{
UseShellExecute = false,

2
samples/ControlCatalog.Desktop/Program.cs

@ -162,7 +162,9 @@ namespace ControlCatalog.Desktop
})
.UseSkia()
.WithInterFont()
#if DEBUG
.WithDeveloperTools()
#endif
.AfterSetup(builder =>
{
EmbedSample.Implementation = OperatingSystem.IsWindows() ? new EmbedSampleWin()

4
samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs

@ -102,8 +102,8 @@ namespace ControlCatalog.Pages
return String.Format("{0} ({1})", parts.ToArray());
});
var binding = new MultiBinding { Converter = converter };
binding.Bindings.Add(new Binding("Name"));
binding.Bindings.Add(new Binding("Abbreviation"));
binding.Bindings.Add(CompiledBinding.Create<StateData, string>(s => s.Name));
binding.Bindings.Add(CompiledBinding.Create<StateData, string>(s => s.Abbreviation));
MultiBindingBox.ValueMemberBinding = binding;

3
samples/ControlCatalog/Pages/CarouselPage/CareCompanionAppPage.xaml.cs

@ -5,6 +5,7 @@ using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
@ -130,7 +131,7 @@ public partial class CareCompanionAppPage : UserControl
};
pager.Bind(PipsPager.SelectedPageIndexProperty,
new Avalonia.Data.Binding("SelectedIndex") { Source = carousel, Mode = Avalonia.Data.BindingMode.TwoWay });
CompiledBinding.Create<AvaCarouselPage, int>(c => c.SelectedIndex, carousel, mode: BindingMode.TwoWay));
return pager;
}

7
samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs

@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@ -38,9 +39,11 @@ namespace ControlCatalog.Pages
"Files",
async d =>
{
if (Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName is { } name &&
var currentFile = Environment.ProcessPath;
if (File.Exists(currentFile) &&
TopLevel.GetTopLevel(this) is { } topLevel &&
await topLevel.StorageProvider.TryGetFileFromPathAsync(name) is { } storageFile)
await topLevel.StorageProvider.TryGetFileFromPathAsync(currentFile) is { } storageFile)
{
d.Add(DataTransferItem.Create(DataFormat.File, storageFile));
}

6
samples/ControlCatalog/Pages/NotificationsPage.xaml

@ -17,11 +17,7 @@
<TextBlock DockPanel.Dock="Top"
Margin="2" Classes="h2" TextWrapping="Wrap">XAML only notification manager.</TextBlock>
<Button DockPanel.Dock="Top"
Content="Show XAML only Notification" Command="{Binding #ControlNotifications.Show}">
<Button.CommandParameter>
<Notification Title="Title" Message="Message" OnClick="NotificationOnClick" />
</Button.CommandParameter>
</Button>
Content="Show XAML only Notification" Click="ShowNotification" />
<Border Padding="10" BorderBrush="{DynamicResource SystemAccentColor}">
<WindowNotificationManager x:Name="ControlNotifications" />
</Border>

10
samples/ControlCatalog/Pages/NotificationsPage.xaml.cs

@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Interactivity;
using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
@ -25,9 +26,14 @@ namespace ControlCatalog.Pages
_viewModel.NotificationManager = new WindowNotificationManager(TopLevel.GetTopLevel(this)!);
}
public void NotificationOnClick()
private void ShowNotification(object? sender, RoutedEventArgs e)
{
ControlNotifications.Show("Notification clicked");
ControlNotifications.Show(new Notification
{
OnClick = () => ControlNotifications.Show("Notification clicked"),
Title = "Title",
Message = "Message"
});
}
}
}

2
samples/GpuInterop/Program.cs

@ -34,7 +34,9 @@ namespace GpuInterop
UseDebug = true
}
})
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace(LogEventLevel.Debug, "Vulkan");
}
}

2
samples/IntegrationTestApp/Program.cs

@ -31,7 +31,9 @@ namespace IntegrationTestApp
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.AfterSetup(builder =>
{
NativeTextBox.Factory =

4
samples/RenderDemo/App.xaml.cs

@ -31,7 +31,9 @@ namespace RenderDemo
OverlayPopups = true,
})
.UsePlatformDetect()
.WithDeveloperTools()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}
}

2
samples/SafeAreaDemo.Desktop/Program.cs

@ -16,7 +16,9 @@ namespace SafeAreaDemo.Desktop
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}
}

2
samples/Sandbox/Program.cs

@ -10,7 +10,9 @@ namespace Sandbox
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}
}

2
samples/TextTestApp/Program.cs

@ -23,7 +23,9 @@ namespace TextTestApp
{
return AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
}
}

2
samples/VirtualizationDemo/Program.cs

@ -7,7 +7,9 @@ class Program
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
#if DEBUG
.WithDeveloperTools()
#endif
.LogToTrace();
public static int Main(string[] args)

18
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs

@ -21,7 +21,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="uri">The URI of the XAML being loaded.</param>
/// <param name="designMode">Indicates whether the XAML is being loaded in design mode.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static object Load([StringSyntax(StringSyntaxAttribute.Xml)] string xaml, Assembly? localAssembly = null, object? rootInstance = null, Uri? uri = null, bool designMode = false)
{
xaml = xaml ?? throw new ArgumentNullException(nameof(xaml));
@ -41,7 +42,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="uri">The URI of the XAML being loaded.</param>
/// <param name="designMode">Indicates whether the XAML is being loaded in design mode.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static object Load(Stream stream, Assembly? localAssembly = null, object? rootInstance = null, Uri? uri = null,
bool designMode = false)
=> AvaloniaXamlIlRuntimeCompiler.Load(new RuntimeXamlLoaderDocument(uri, rootInstance, stream),
@ -53,7 +55,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="document">The stream containing the XAML.</param>
/// <param name="configuration">Xaml loader configuration.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration? configuration = null)
=> AvaloniaXamlIlRuntimeCompiler.Load(document, configuration ?? new RuntimeXamlLoaderConfiguration());
@ -63,7 +66,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="documents">Collection of documents.</param>
/// <param name="configuration">Xaml loader configuration.</param>
/// <returns>The loaded objects per each input document. If document was removed, the element by index is null.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static IReadOnlyList<object?> LoadGroup(IReadOnlyCollection<RuntimeXamlLoaderDocument> documents, RuntimeXamlLoaderConfiguration? configuration = null)
=> AvaloniaXamlIlRuntimeCompiler.LoadGroup(documents, configuration ?? new RuntimeXamlLoaderConfiguration());
@ -73,7 +77,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="xaml">The string containing the XAML.</param>
/// <param name="localAssembly">Default assembly for clr-namespace:.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static object Parse([StringSyntax(StringSyntaxAttribute.Xml)] string xaml, Assembly? localAssembly = null)
=> Load(xaml, localAssembly);
@ -84,7 +89,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="xaml">>The string containing the XAML.</param>
/// <param name="localAssembly">>Default assembly for clr-namespace:.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
public static T Parse<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>([StringSyntax(StringSyntaxAttribute.Xml)] string xaml, Assembly? localAssembly = null)
=> (T)Parse(xaml, localAssembly);
}

85
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

@ -28,7 +28,8 @@ using XamlX.IL.Cecil;
namespace Avalonia.Markup.Xaml.XamlIl
{
#if !RUNTIME_XAML_CECIL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
[RequiresUnreferencedCode(XamlX.TrimmingMessages.Sre)]
[RequiresDynamicCode(XamlX.TrimmingMessages.Sre)]
#endif
internal static class AvaloniaXamlIlRuntimeCompiler
{
@ -41,30 +42,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
private static XamlLanguageEmitMappings<IXamlILEmitter, XamlILNodeEmitResult>? _sreEmitMappings;
private static XamlXmlnsMappings? _sreXmlns;
private static AssemblyBuilder? _sreAsm;
private static bool _sreCanSave;
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
public static void DumpRuntimeCompilationResults()
{
if (_sreBuilder == null)
return;
var saveMethod = _sreAsm!.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "Save" && m.GetParameters().Length == 1);
if (saveMethod == null)
return;
try
{
_sreBuilder.CreateGlobalFunctions();
saveMethod.Invoke(_sreAsm, new Object[] {"XamlIlLoader.ildump"});
}
catch
{
//Ignore
}
}
[CompilerDynamicDependencies]
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
[MemberNotNull(nameof(_sreTypeSystem))]
[MemberNotNull(nameof(_sreBuilder))]
[MemberNotNull(nameof(_sreMappings))]
@ -74,7 +53,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
[MemberNotNull(nameof(_ignoresAccessChecksFromAttribute))]
static void InitializeSre()
{
// SRE backend doesn't load assemblies, unless they are already in the memory.
// SRE backend doesn't load assemblies unless they are already in the memory.
// At the very least, we should make sure that assemblies necessary for `AvaloniaXamlIlWellKnownTypes` are loaded.
// Root `Avalonia.Controls`.
GC.KeepAlive(typeof(Avalonia.Controls.Control));
@ -87,26 +66,10 @@ namespace Avalonia.Markup.Xaml.XamlIl
_sreTypeSystem = new SreTypeSystem();
if (_sreBuilder == null)
{
_sreCanSave = !(RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"));
var name = new AssemblyName(Guid.NewGuid().ToString("N"));
if (_sreCanSave)
{
var define = GetDefineDynamicAssembly();
if (define != null)
_sreAsm = (AssemblyBuilder)define.Invoke(AppDomain.CurrentDomain, new object[]
{
name, (AssemblyBuilderAccess)3,
Path.GetDirectoryName(typeof(AvaloniaXamlIlRuntimeCompiler).Assembly.GetModules()[0]
.FullyQualifiedName)!
})!;
else
_sreCanSave = false;
}
if(_sreAsm == null)
_sreAsm = AssemblyBuilder.DefineDynamicAssembly(name,
AssemblyBuilderAccess.RunAndCollect);
_sreAsm ??= AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndCollect);
_sreBuilder = _sreAsm.DefineDynamicModule("XamlIlLoader.ildump");
}
@ -123,12 +86,6 @@ namespace Avalonia.Markup.Xaml.XamlIl
_ignoresAccessChecksFromAttribute = EmitIgnoresAccessCheckAttributeDefinition(_sreBuilder);
}
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
static MethodInfo? GetDefineDynamicAssembly() => AppDomain.CurrentDomain.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "DefineDynamicAssembly"
&& m.GetParameters().Length == 3 &&
m.GetParameters()[2].ParameterType == typeof(string));
static Type EmitIgnoresAccessCheckAttributeDefinition(ModuleBuilder builder)
{
var tb = builder.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute",
@ -237,37 +194,15 @@ namespace Avalonia.Markup.Xaml.XamlIl
return result;
}
static object LoadSre(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
public static object LoadSre(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
{
var success = false;
try
{
var rv = LoadSreCore(document, configuration);
success = true;
return rv;
}
finally
{
if(!success && _sreCanSave)
DumpRuntimeCompilationResults();
}
return LoadSreCore(document, configuration);
}
static IReadOnlyList<object> LoadGroupSre(IReadOnlyCollection<RuntimeXamlLoaderDocument> documents,
public static IReadOnlyList<object> LoadGroupSre(IReadOnlyCollection<RuntimeXamlLoaderDocument> documents,
RuntimeXamlLoaderConfiguration configuration)
{
var success = false;
try
{
var rv = LoadGroupSreCore(documents, configuration);
success = true;
return rv;
}
finally
{
if(!success && _sreCanSave)
DumpRuntimeCompilationResults();
}
return LoadGroupSreCore(documents, configuration);
}
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]

Loading…
Cancel
Save