chore: Introductory support for NativeAOT builds#1233
Draft
chore: Introductory support for NativeAOT builds#1233
Conversation
e4c85b8 to
4a9173e
Compare
jonpryor
added a commit
to unoplatform/ShowMeTheXAML
that referenced
this pull request
Jan 29, 2026
Context: unoplatform/Uno.Gallery#1233 Context: unoplatform/uno-private#1696 (comment) What do we want? To build and run Uno.Gallery with NativeAOT! (See also: unoplatform/Uno.Gallery#1233) We also want Uno.Gallery to run *properly*. The problem: The "`<>` Show XAML" button doesn't work properly. Use unoplatform/Uno.Gallery#1233 to build and run Uno.Gallery with NativeAOT: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:SkiaPublishAot=true ./Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery Once the app has launched, select **UI components > AutoSuggestBox** in the left-hand tree. Then, in the right-hand panel, click the "`<>` Show XAML" button. Expected results: *Something is shown*. Actual results: An empty box is shown. As with most NativeAOT-related issues, this is due to Reflection: `XamlDisplay.Init()` tries to lookup the `ShowMeTheXAML.XamlDictionary` type from an `Assembly`. By default, nothing is statically referencing `XamlDictionary`, so it isn't accessible via Reflection, so this attempted lookup (silently) fails. This aspect can be worked around in Uno.Gallery via [`[DynamicDependency]`][0], e.g. diff --git a/Uno.Gallery/App.xaml.cs b/Uno.Gallery/App.xaml.cs index 51ae161a..45b16dfd 100644 --- a/Uno.Gallery/App.xaml.cs +++ b/Uno.Gallery/App.xaml.cs @@ -78,6 +78,7 @@ namespace Uno.Gallery } } + [System.Diagnostics.CodeAnalysis.DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ShowMeTheXAML.XamlDictionary))] private void OnLaunchedOrActivated() { MainWindow = new Window(); The problem is that once `XamlDisplay.Init()` finds `XamlDictionary`, it then attempts to invoke its static constructor: //Invoke the static constructor global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(xamlDictionary.TypeHandle); *This* fails, hard: System.NotSupportedException: 'ShowMeTheXAML.XamlDictionary' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.TypeInfos.RuntimeTypeInfo.get_TypeHandle() + 0x95 at ShowMeTheXAML.XamlDisplay.<Init>g__LoadFromAssembly|7_0(Assembly) + 0x4d at ShowMeTheXAML.XamlDisplay.Init(Assembly[]) + 0x47 at Uno.Gallery.App..ctor() + 0x99 at Uno.Gallery.Program.<>c.<Main>b__0_0() + 0x18 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.<StartApp>g__CreateApp|18_0(ApplicationInitializationCallbackParams _) + 0x21 at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback) + 0x70 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.StartApp() + 0xbc Address this by removing the *need* for Reflection: update the `XamlDictionary` templates to contain a static `Init()` method: partial class XamlDictionary { public static void Init() { } } This allows Uno.Gallery to *explicitly* call `XamlDictionary.Init()`, which *implicitly* invokes the `XamlDictionary` static constructor, avoiding the need for Reflection *entirely*. This in turn allows the "`<>` Show XAML" button to work properly. Additionally, make the `XamlDictionary` declaration `partial`, so that if future "workarounds" such as `Init()` are needed, a new `Uno.ShowMeTheXAML.MSBuild` NuGet package isn't required. [0]: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.dynamicdependencyattribute?view=net-9.0
5 tasks
jonpryor
added a commit
to unoplatform/ShowMeTheXAML
that referenced
this pull request
Jan 30, 2026
Context: unoplatform/Uno.Gallery#1233 Context: unoplatform/uno-private#1696 (comment) What do we want? To build and run Uno.Gallery with NativeAOT! (See also: unoplatform/Uno.Gallery#1233) We also want Uno.Gallery to run *properly*. The problem: The "`<>` Show XAML" button doesn't work properly. Use unoplatform/Uno.Gallery#1233 to build and run Uno.Gallery with NativeAOT: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:SkiaPublishAot=true ./Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery Once the app has launched, select **UI components > AutoSuggestBox** in the left-hand tree. Then, in the right-hand panel, click the "`<>` Show XAML" button. Expected results: *Something is shown*. Actual results: An empty box is shown. As with most NativeAOT-related issues, this is due to Reflection: `XamlDisplay.Init()` tries to lookup the `ShowMeTheXAML.XamlDictionary` type from an `Assembly`. By default, nothing is statically referencing `XamlDictionary`, so it isn't accessible via Reflection, so this attempted lookup (silently) fails. This aspect can be worked around in Uno.Gallery via [`[DynamicDependency]`][0], e.g. diff --git a/Uno.Gallery/App.xaml.cs b/Uno.Gallery/App.xaml.cs index 51ae161a..45b16dfd 100644 --- a/Uno.Gallery/App.xaml.cs +++ b/Uno.Gallery/App.xaml.cs @@ -78,6 +78,7 @@ namespace Uno.Gallery } } + [System.Diagnostics.CodeAnalysis.DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ShowMeTheXAML.XamlDictionary))] private void OnLaunchedOrActivated() { MainWindow = new Window(); The problem is that once `XamlDisplay.Init()` finds `XamlDictionary`, it then attempts to invoke its static constructor: //Invoke the static constructor global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(xamlDictionary.TypeHandle); *This* fails, hard: System.NotSupportedException: 'ShowMeTheXAML.XamlDictionary' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.TypeInfos.RuntimeTypeInfo.get_TypeHandle() + 0x95 at ShowMeTheXAML.XamlDisplay.<Init>g__LoadFromAssembly|7_0(Assembly) + 0x4d at ShowMeTheXAML.XamlDisplay.Init(Assembly[]) + 0x47 at Uno.Gallery.App..ctor() + 0x99 at Uno.Gallery.Program.<>c.<Main>b__0_0() + 0x18 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.<StartApp>g__CreateApp|18_0(ApplicationInitializationCallbackParams _) + 0x21 at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback) + 0x70 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.StartApp() + 0xbc Address this by removing the *need* for Reflection: update the `XamlDictionary` templates to contain a static `Init()` method: partial class XamlDictionary { public static void Init() { } } This allows Uno.Gallery to *explicitly* call `XamlDictionary.Init()`, which *implicitly* invokes the `XamlDictionary` static constructor, avoiding the need for Reflection *entirely*. This in turn allows the "`<>` Show XAML" button to work properly. Additionally, make the `XamlDictionary` declaration `partial`, so that if future "workarounds" such as `Init()` are needed, a new `Uno.ShowMeTheXAML.MSBuild` NuGet package isn't required. [0]: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.dynamicdependencyattribute?view=net-9.0
jonpryor
added a commit
to unoplatform/ShowMeTheXAML
that referenced
this pull request
Jan 30, 2026
Context: unoplatform/Uno.Gallery#1233 Context: unoplatform/uno-private#1696 (comment) What do we want? To build and run Uno.Gallery with NativeAOT! (See also: unoplatform/Uno.Gallery#1233) We also want Uno.Gallery to run *properly*. The problem: The "`<>` Show XAML" button doesn't work properly. Use unoplatform/Uno.Gallery#1233 to build and run Uno.Gallery with NativeAOT: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:SkiaPublishAot=true ./Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery Once the app has launched, select **UI components > AutoSuggestBox** in the left-hand tree. Then, in the right-hand panel, click the "`<>` Show XAML" button. Expected results: *Something is shown*. Actual results: An empty box is shown. As with most NativeAOT-related issues, this is due to Reflection: `XamlDisplay.Init()` tries to lookup the `ShowMeTheXAML.XamlDictionary` type from an `Assembly`. By default, nothing is statically referencing `XamlDictionary`, so it isn't accessible via Reflection, so this attempted lookup (silently) fails. This aspect can be worked around in Uno.Gallery via [`[DynamicDependency]`][0], e.g. diff --git a/Uno.Gallery/App.xaml.cs b/Uno.Gallery/App.xaml.cs index 51ae161a..45b16dfd 100644 --- a/Uno.Gallery/App.xaml.cs +++ b/Uno.Gallery/App.xaml.cs @@ -78,6 +78,7 @@ namespace Uno.Gallery } } + [System.Diagnostics.CodeAnalysis.DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ShowMeTheXAML.XamlDictionary))] private void OnLaunchedOrActivated() { MainWindow = new Window(); The problem is that once `XamlDisplay.Init()` finds `XamlDictionary`, it then attempts to invoke its static constructor: //Invoke the static constructor global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(xamlDictionary.TypeHandle); *This* fails, hard: System.NotSupportedException: 'ShowMeTheXAML.XamlDictionary' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.TypeInfos.RuntimeTypeInfo.get_TypeHandle() + 0x95 at ShowMeTheXAML.XamlDisplay.<Init>g__LoadFromAssembly|7_0(Assembly) + 0x4d at ShowMeTheXAML.XamlDisplay.Init(Assembly[]) + 0x47 at Uno.Gallery.App..ctor() + 0x99 at Uno.Gallery.Program.<>c.<Main>b__0_0() + 0x18 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.<StartApp>g__CreateApp|18_0(ApplicationInitializationCallbackParams _) + 0x21 at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback) + 0x70 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.StartApp() + 0xbc Address this by removing the *need* for Reflection: update the `XamlDictionary` templates to contain a static `Init()` method: partial class XamlDictionary { public static void Init() { } } This allows Uno.Gallery to *explicitly* call `XamlDictionary.Init()`, which *implicitly* invokes the `XamlDictionary` static constructor, avoiding the need for Reflection *entirely*. This in turn allows the "`<>` Show XAML" button to work properly. Additionally, make the `XamlDictionary` declaration `partial`, so that if future "workarounds" such as `Init()` are needed, a new `Uno.ShowMeTheXAML.MSBuild` NuGet package isn't required. [0]: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.dynamicdependencyattribute?view=net-9.0
jonpryor
added a commit
to unoplatform/ShowMeTheXAML
that referenced
this pull request
Jan 30, 2026
Context: unoplatform/Uno.Gallery#1233 Context: unoplatform/uno-private#1696 (comment) What do we want? To build and run Uno.Gallery with NativeAOT! (See also: unoplatform/Uno.Gallery#1233) We also want Uno.Gallery to run *properly*. The problem: The "`<>` Show XAML" button doesn't work properly. Use unoplatform/Uno.Gallery#1233 to build and run Uno.Gallery with NativeAOT: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:SkiaPublishAot=true ./Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery Once the app has launched, select **UI components > AutoSuggestBox** in the left-hand tree. Then, in the right-hand panel, click the "`<>` Show XAML" button. Expected results: *Something is shown*. Actual results: An empty box is shown. As with most NativeAOT-related issues, this is due to Reflection: `XamlDisplay.Init()` tries to lookup the `ShowMeTheXAML.XamlDictionary` type from an `Assembly`. By default, nothing is statically referencing `XamlDictionary`, so it isn't accessible via Reflection, so this attempted lookup (silently) fails. This aspect can be worked around in Uno.Gallery via [`[DynamicDependency]`][0], e.g. diff --git a/Uno.Gallery/App.xaml.cs b/Uno.Gallery/App.xaml.cs index 51ae161a..45b16dfd 100644 --- a/Uno.Gallery/App.xaml.cs +++ b/Uno.Gallery/App.xaml.cs @@ -78,6 +78,7 @@ namespace Uno.Gallery } } + [System.Diagnostics.CodeAnalysis.DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ShowMeTheXAML.XamlDictionary))] private void OnLaunchedOrActivated() { MainWindow = new Window(); The problem is that once `XamlDisplay.Init()` finds `XamlDictionary`, it then attempts to invoke its static constructor: //Invoke the static constructor global::System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(xamlDictionary.TypeHandle); *This* fails, hard: System.NotSupportedException: 'ShowMeTheXAML.XamlDictionary' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.TypeInfos.RuntimeTypeInfo.get_TypeHandle() + 0x95 at ShowMeTheXAML.XamlDisplay.<Init>g__LoadFromAssembly|7_0(Assembly) + 0x4d at ShowMeTheXAML.XamlDisplay.Init(Assembly[]) + 0x47 at Uno.Gallery.App..ctor() + 0x99 at Uno.Gallery.Program.<>c.<Main>b__0_0() + 0x18 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.<StartApp>g__CreateApp|18_0(ApplicationInitializationCallbackParams _) + 0x21 at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback) + 0x70 at Uno.UI.Runtime.Skia.MacOS.MacSkiaHost.StartApp() + 0xbc Address this by removing the *need* for Reflection: update the `XamlDictionary` templates to contain a static `Init()` method: partial class XamlDictionary { public static void Init() { } } This allows Uno.Gallery to *explicitly* call `XamlDictionary.Init()`, which *implicitly* invokes the `XamlDictionary` static constructor, avoiding the need for Reflection *entirely*. This in turn allows the "`<>` Show XAML" button to work properly. Additionally, make the `XamlDictionary` declaration `partial`, so that if future "workarounds" such as `Init()` are needed, a new `Uno.ShowMeTheXAML.MSBuild` NuGet package isn't required. [0]: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.dynamicdependencyattribute?view=net-9.0
4a9173e to
a7f8427
Compare
|
|
bff0328 to
c0c7d82
Compare
|
|
bce852a to
9061849
Compare
|
|
jonpryor
added a commit
to unoplatform/uno
that referenced
this pull request
Feb 4, 2026
Context: unoplatform/Uno.Gallery#1233 While trying to get Uno Gallery working with Android+Native AOT: dotnet publish -m:1 -c Release -r android-x64 -f net10.0-android -p:TargetFrameworkOverride=net10.0-android \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SkiaPublishAot=true adb install Uno.Gallery/bin/Release/net10.0-android/android-x64/publish/com.nventive.uno.ui.demo-Signed.apk adb shell am start com.nventive.uno.ui.demo/crc64a57a145253f0f267.MainActivity The app would crash at startup: E DOTNET : Unhandled exception. E DOTNET : System.Reflection.TargetInvocationException: Arg_TargetInvocationException E DOTNET : ---> System.Exception: Failed to load icuuc. E DOTNET : at Microsoft.UI.Xaml.Documents.UnicodeText.ICU.Init() + 0x338 E DOTNET : at libUno.Gallery!<BaseAddress>+0x570efa9 E DOTNET : at System.Reflection.DynamicInvokeInfo.InvokeWithFewArguments(IntPtr, Byte&, Byte&, Object[], BinderBundle, Boolean) + 0x91 E DOTNET : Exception_EndOfInnerExceptionStack E DOTNET : at System.Reflection.DynamicInvokeInfo.InvokeWithFewArguments(IntPtr, Byte&, Byte&, Object[], BinderBundle, Boolean) + 0x11f E DOTNET : at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0xba E DOTNET : at Internal.Reflection.Execution.MethodInvokers.StaticMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x20 E DOTNET : at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 E DOTNET : at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 E DOTNET : at __IcuDa The cause of the crash is *not* that `icuuc` could not be loaded, unlike what the exception messages says. Instead, the problem is that the `u_getVersion_N` symbol could not be found, where `N` is a value in range [67-100]. The Android emulator that @jonpryor was using was for API-28, which is version *60*: % adb pull /system/lib/libicuuc.so % nm -D libicuuc.so| grep u_getV 00077580 T u_getVersion_60 Expand the range of versions probed to [50-100], which covers Android API-21+. (API-21 has `u_getVersion_53`.). This allows ICU to be initialized correctly on Android API-21+.
5 tasks
9061849 to
95acf1e
Compare
|
|
95acf1e to
f93a246
Compare
Context: unoplatform/uno@559b1f7 Context: unoplatform/uno.toolkit.ui@3ef6d6c Context: unoplatform/ShowMeTheXAML#30 What do we want? To build and run with Native AOT! Which in turn requires Uno.Sdk 6.6.0 or later: sed -i '' 's/"Uno.Sdk": ".*"/"Uno.Sdk": "6.6.0-dev.15"/g' global.json dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:PublishAot=true …which promptly fails to build: …Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(120,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. ~~ Build Support for Native AOT ~~ This specifically happens because `Uno.Gallery.csproj` has a `@(ProjectReference)` to `Uno.Gallery.SourceGenerators.csproj`, which is a .NET Standard 2.0 project, which doesn't support Native AOT. To fix this, we need an "indirection": a property which we can set on the command-line which causes `$(PublishAot)` to be set. The "conventional" indirection used in unoplatform/uno SamplesApp and in unoplatform/uno.chefs is `$(SkiaPublishAot)`. This allows: dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true \ -p:SkiaPublishAot=true \ -p:EmitCompilerGeneratedFiles=true -p:CompilerGeneratedFilesOutputPath=`pwd`/_gen which *builds* successfully. (It doesn't *run* successfully yet; that's for later.) ~~ Build Support for Android + Native AOT ~~ Remove `$(RunAOTCompilation)` from the Android build, as it's presence prevents use of Native AOT on Android: /usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/36.1.12/targets/Microsoft.Android.Sdk.Aot.targets(123,5): error Precompiling failed for …/Uno.Gallery/obj/Release/net10.0-android/android-x64/aot-in/System.Collections.dll with exit code 134. Runtime critical type System.RuntimeMethodHandle not found # and 24 more similar errors ~~ Build Support for Mobile Side-by-Side Installation ~~ Additionally, to "reasonably easily" support side-by-side execution of Uno Gallery builds on e.g. iOS or Android, introduce support for the following MSBuild properties (also done in unoplatform/uno.chefs): * `$(ApplicationIdVendorSuffix)`: Value to append to `$(ApplicationId)`, so that separate builds have separate names. * `$(ApplicationTitleVendorSuffix)`: Value to append to `$(ApplicationTitle)`, so that the different builds are distinguishable on app launchers. On iOS, this allows side-by-side installs, but the iOS build doesn't use the `$(ApplicationTitle)` value. This is because `Uno.Gallery/Platforms/iOS/Info.plist` already had a `CFBundleDisplayName` entry, which overrides `$(ApplicationTitle)`. Remove the `CFBundleDisplayName` entry so that `$(ApplicationTitle)` can be used to control `CFBundleDisplayName`. ~~ Desktop Startup Timing ~~ Introduce a trivial "hack" to support app starting time comparisons: add a `--exit` command-line argument which causes the app to `Exit()` at the end of `App.OnLaunched()`. This allows using **time**(1) to capture "app startup time": # CoreCLR: % dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true % time Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery --exit Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery --exit 1.08s user 0.32s system 70% cpu 1.982 total # Native AOT: % dotnet publish -c Release -r osx-x64 -f net10.0-desktop -p:TargetFrameworkOverride=net10.0-desktop \ -bl Uno.Gallery/Uno.Gallery.csproj -p:UseSkiaRendering=true -p:SelfContained=true -p:SkiaPublishAot=true % time Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery --exit Uno.Gallery/bin/Release/net10.0-desktop/osx-x64/publish/Uno.Gallery --exit 0.27s user 0.15s system 51% cpu 0.811 total Or on Windows: Measure-Command { .\Uno.Gallery\bin\Release\net10.0-desktop\win-x64\publish\Uno.Gallery.exe --exit | Out-Default } | Select TotalMilliseconds ~~ iOS Startup Timing ~~ No changes are needed; to capture startup time on iOS: 1. Install the `.ipa` onto your iOS device. 2. Open **Instruments** (launch Xcode, then click Xcode > Open Developer Tool > Instruments) 3. In Instruments, click File > New ⌘N. 4. In the **Choose a Template…** window, select **App Launch**. 5. In the Window which appears, in the central area is a **Target** section; from the **Device** dropdown, select your connected iOS device, and from the **Target** dropdowns, select **Launch** and the Uno Gallery app from the dropdown. Note: the Target dropdown shows `CFBundleExecutable` -- which is identical regardless of `$(ApplicationIdVendorSuffix)` or `$(ApplicationTitleVendorSuffix)` -- so this is easiest to do if there is only *one* Uno.Gallery app installed. 6. Click File > Record Trace ⌘R to start recording, which will launch the app on the device. 7. When the app has finished launching, force-quit the app. Instruments will now start processing the data. 8. Type ⌘4 to switch to **App Lifecycle**. This shows a table of events with Start, Duration, and Narrative columns. Look for the *Launching - Initial Frame Rendering* Narrative entry. The Start value is the time taken to launch the app. | Start | Duration | Narrative | | ------------: | --------: | :------------------------------------------------ | | 00:00.000.000 | 480.77 ms | The system took 480.77 ms to create the process. | | … | … | … | | 00:01.306.446 | 4.41 ms | Launching – Initial Frame Rendering | In this run, app startup time was 1.306 seconds. ~~ Native AOT Runtime Fixes ~~ Begin fixing some of the runtime issues with Native AOT builds. The following messages would appear on the Console during startup: fail: Uno.Gallery.Sample[0] Failed to initialize data for `AutoSuggestBoxSamplePage`. dataType: Uno.Gallery.Views.Samples.AutoSuggestBoxSamplePageViewModel. Exception: System.MissingMethodException: No parameterless constructor defined for type 'Uno.Gallery.Views.Samples.AutoSuggestBoxSamplePageViewModel'. at System.ActivatorImplementation.CreateInstance(Type, Boolean) + 0x180 at Uno.Gallery.Sample.CreateData(Type) + 0x3a fail: Uno.Gallery.Sample[0] Failed to initialize data for `BarometerSamplePage`. dataType: BarometerSamplePageViewModel. Exception: System.MissingMethodException: No parameterless constructor defined for type 'BarometerSamplePageViewModel'. at System.ActivatorImplementation.CreateInstance(Type, Boolean) + 0x180 at Uno.Gallery.Sample.CreateData(Type) + 0x3a Plus 19 more similar messages. These `fail` messages appear because of missing "reflection metadata" (unoplatform/uno@559b1f78), and we can fix these by using the `[DynamicallyAccessedMembers]` and `[DynamicDependency]` attributes. In order to use `[DynamicallyAccessedMembers]`, we need either a generic type parameter or a `typeof()` expression. Searching around, there are useful places `typeof()` is already used; from `Uno.Gallery.SourceGenerators` generated output, in `$(CompilerGeneratedFilesOutputPath)`, we have: // …/App.Samples.g.cs public partial class App { public static Sample[] GetSamples() { return new[] { // … new global::Uno.Gallery.Sample(new global::Uno.Gallery.SamplePageAttribute(category: (global::Uno.Gallery.SampleCategory)(2), title: "AutoSuggestBox", source: (global::Uno.Gallery.SourceSdk)(0), glyph: "") { Description = @"Represents a text control that makes suggestions to users as they enter text.", DocumentationLink = "https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.autosuggestbox?view=windows-app-sdk-1.3", DataType = typeof(global::Uno.Gallery.Views.Samples.AutoSuggestBoxSamplePageViewModel), SortOrder = 2147483647 }, typeof(Uno.Gallery.Views.Samples.AutoSuggestBoxSamplePage)), // … }; } } Which has the handy benefit of containing *both* `AutoSuggestBoxSamplePage` and `AutoSuggestBoxSamplePageViewModel`, which were mentioned in the `fail` message. This in turn makes the fix straightforward: update the `Sample` and `SamplePageAttribute` types to use `[DynamicallyAccessedMembers]` on their respective `Type` parameters and properties to preserve constructors (from the original message) and properties, which almost certainly will be needed anyway. (Property preservation is reflexive at this point.) If you select **UI components > AutoSuggestBox** in the left-side tree view, then click the `<>` "Show XAML" button, nothing is shown *and* the following messages are written to the Console: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ShowMeTheXAML:XamlDisplayExtensions.Header] property getter does not exist on type [ShowMeTheXAML.XamlDisplay] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ShowMeTheXAML:XamlDisplayExtensions.Description] property getter does not exist on type [ShowMeTheXAML.XamlDisplay] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ShowMeTheXAML:XamlDisplayExtensions.Options] property getter does not exist on type [ShowMeTheXAML.XamlDisplay] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ShowMeTheXAML:XamlDisplayExtensions.PrettyXaml] property getter does not exist on type [ShowMeTheXAML.XamlDisplay] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ShowMeTheXAML:XamlDisplayExtensions.ShowXaml] property getter does not exist on type [ShowMeTheXAML.XamlDisplay] This is because WPF Attached Properties require use of `[DynamicDependency]` to ensure that the required methods are accessible via Reflection; see also unoplatform/uno.toolkit.ui@3ef6d6ce. Update all use of `DependencyProperty.RegisterAttached()` so that required methods are retained. Unfortunately, while this fixes the above `fail` messages, clicking the `<>` "Show XAML" button still does nothing. Fixing the `<>` "Show XAML" button requires unoplatform/ShowMeTheXAML#30 and replacing the existing `XamlDisplay.Init()` invocation with `XamlDictionary.Init()`. Bump to Uno.ShowMeTheXAML 2.0.0-dev0026 to get this fix. Unfortunately, this breaks the build: D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Warning As Error: Detected package downgrade: Microsoft.Windows.SDK.BuildTools from 10.0.28000.1-RTM to 10.0.26100.7463. Reference the package directly from the project to select a different version. D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Uno.Gallery -> Uno.ShowMeTheXAML 2.0.0-dev0026 -> Microsoft.Windows.SDK.BuildTools (>= 10.0.28000.1-RTM) D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Uno.Gallery -> Microsoft.Windows.SDK.BuildTools (>= 10.0.26100.7463) D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Warning As Error: Detected package downgrade: Microsoft.WindowsAppSDK from 1.8.260101001 to 1.7.250909003. Reference the package directly from the project to select a different version. D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Uno.Gallery -> Uno.ShowMeTheXAML 2.0.0-dev0026 -> Microsoft.WindowsAppSDK (>= 1.8.260101001) D:\a\1\s\Uno.Gallery\Uno.Gallery.csproj : error NU1605: Uno.Gallery -> Microsoft.WindowsAppSDK (>= 1.7.250909003) Fix this error by explicitly adding `Microsoft.WindowsAppSDK` and `Microsoft.Windows.SDK.BuildTools` NuGet package references which match the versions used by `Uno.ShowMeTheXAML`. If you select **UI components > BreadcrumbBar** in the left-side tree view, then the **BreadcrumbBar with Custom DataTemplate** section on the right-hand page doesn't show anything, and Console output contains: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [Name] property getter does not exist on type [Uno.Gallery.Entities.Data.Folder] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [ItemCount] property getter does not exist on type [Uno.Gallery.Entities.Data.Folder] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [Description] property getter does not exist on type [Uno.Gallery.Entities.Data.Folder] Fix this by adding `[Microsoft.UI.Xaml.Data.Bindable]` to `Uno.Gallery.Entities.Data.Folder`. The use of `[Bindable]` causes the `Uno.UI.SourceGenerators.BindableTypeProvider` source generator to emit `BindableType(…, typeof(Folder))` to `BindableMetadata.g.cs`, which cause all public properties to be added to reflection metadata. Add `[Bindable]` to all other types containing properties within `Uno.Gallery.Entities.Data`. This fixes a number of other samples and messages such as: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [Color] property getter does not exist on type [Uno.Gallery.Entities.Data.Record] If you select **UI features > Binding** in the left-side tree view, the right-hand panel would be subtly different between CoreCLR and Native AOT: * CoreCLR: `The length is: [empty]` * Native AOT: `The length is:` Worse, if you enter text into "myTextBox", the bound fields properly update under CoreCLR. For example, enter "123" into "myTextBox", and CoreCLR would show: > The text of myTextBox is: 123 > The length is: 3 Under Native AOT, *nothing* updates. Console output contains: fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [Text] property getter does not exist on type [Uno.Gallery.Views.Samples.BindingSamplePageViewModel] fail: Uno.UI.DataBinding.BindingPropertyHelper[0] The [TextLength] property getter does not exist on type [Uno.Gallery.Views.Samples.BindingSamplePageViewModel] Fix this by adding `[Bindable]` to `BindingSamplePageViewModel`. (Which means "just add `[Bindable]`!" is quickly becoming my favorite answer to everything. Unless the type has `required` or `init`-only properties; see also unoplatform/uno.chefs@06f4f804.) Continue this pattern: update all types which implement `INotifyPropertyChanged` or inherit from a type which implements `INotifyPropertyChanged` to have `[Bindable]`. This fixes the following `fail` messages, among others: The [AccelerationX] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [AccelerationY] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [AccelerationZ] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [AccelerometerAvailable] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [ButtonContent] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [ButtonContent] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [GeolocatedAccuracy] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [GeolocatedAltitude] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [GeolocatedLatitude] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [GeolocatedLongitude] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [GeolocatedTimestamp] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel] The [LastReadTimestamp] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [LastShakeTimestamp] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [ListenButtonContent] property getter does not exist on type [Uno.Gallery.Views.Samples.ClipboardSamplePageViewModel] The [Message] property getter does not exist on type [Uno.Gallery.Views.Samples.ClipboardSamplePageViewModel] The [ReportInterval] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [ShakeCount] property getter does not exist on type [Uno.Gallery.Views.Samples.AccelerometerSamplePageViewModel] The [ToggleButtonContent] property getter does not exist on type [Uno.Gallery.Views.Samples.GeolocatorSamplePageViewModel]
f93a246 to
0ab8c3e
Compare
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context: unoplatform/uno@559b1f7
Context: unoplatform/uno.toolkit.ui@3ef6d6c
Context: unoplatform/ShowMeTheXAML#30
What do we want? To build and run with Native AOT!
Which in turn requires Uno.Sdk 6.6.0 or later:
…which promptly fails to build:
~~ Build Support for Native AOT ~~
This specifically happens because
Uno.Gallery.csprojhas a@(ProjectReference)toUno.Gallery.SourceGenerators.csproj, whichis a .NET Standard 2.0 project, which doesn't support Native AOT.
To fix this, we need an "indirection": a property which we can set on
the command-line which causes
$(PublishAot)to be set.The "conventional" indirection used in unoplatform/uno SamplesApp and
in unoplatform/uno.chefs is
$(SkiaPublishAot). This allows:which builds successfully. (It doesn't run successfully yet;
that's for later.)
~~ Build Support for Android + Native AOT ~~
Remove
$(RunAOTCompilation)from the Android build, as it'spresence prevents use of Native AOT on Android:
~~ Build Support for Mobile Side-by-Side Installation ~~
Additionally, to "reasonably easily" support side-by-side execution
of Uno Gallery builds on e.g. iOS or Android, introduce support for
the following MSBuild properties (also done in unoplatform/uno.chefs):
$(ApplicationIdVendorSuffix): Value to append to$(ApplicationId), so that separate builds have separate names.$(ApplicationTitleVendorSuffix): Value to append to$(ApplicationTitle), so that the different builds aredistinguishable on app launchers.
On iOS, this allows side-by-side installs, but the iOS build doesn't
use the
$(ApplicationTitle)value. This is becauseUno.Gallery/Platforms/iOS/Info.plistalready had aCFBundleDisplayNameentry, which overrides$(ApplicationTitle).Remove the
CFBundleDisplayNameentry so that$(ApplicationTitle)can be used to control
CFBundleDisplayName.~~ Desktop Startup Timing ~~
Introduce a trivial "hack" to support app starting time comparisons:
add a
--exitcommand-line argument which causes the app toExit()at the end of
App.OnLaunched(). This allows using time(1) tocapture "app startup time":
Or on Windows:
~~ iOS Startup Timing ~~
No changes are needed; to capture startup time on iOS:
Install the
.ipaonto your iOS device.Open Instruments (launch Xcode, then
click Xcode > Open Developer Tool > Instruments)
In Instruments, click File > New ⌘N.
In the Choose a Template… window, select App Launch.
In the Window which appears, in the central area is a Target
section; from the Device dropdown, select your connected iOS
device, and from the Target dropdowns, select Launch and
the Uno Gallery app from the dropdown.
Note: the Target dropdown shows
CFBundleExecutable-- which isidentical regardless of
$(ApplicationIdVendorSuffix)or$(ApplicationTitleVendorSuffix)-- so this is easiest to do ifthere is only one Uno.Gallery app installed.
Click File > Record Trace ⌘R to start recording, which will launch
the app on the device.
When the app has finished launching, force-quit the app.
Instruments will now start processing the data.
Type ⌘4 to switch to App Lifecycle. This shows a table of
events with Start, Duration, and Narrative columns.
Look for the Launching - Initial Frame Rendering Narrative entry.
The Start value is the time taken to launch the app.
In this run, app startup time was 1.306 seconds.
~~ Native AOT Runtime Fixes ~~
Begin fixing some of the runtime issues with Native AOT builds.
The following messages would appear on the Console during startup:
Plus 19 more similar messages.
These
failmessages appear because of missing "reflection metadata"(unoplatform/uno@559b1f78), and we can fix these by using the
[DynamicallyAccessedMembers]and[DynamicDependency]attributes.In order to use
[DynamicallyAccessedMembers], we need either ageneric type parameter or a
typeof()expression. Searching around,there are useful places
typeof()is already used; fromUno.Gallery.SourceGeneratorsgenerated output, in$(CompilerGeneratedFilesOutputPath), we have:Which has the handy benefit of containing both
AutoSuggestBoxSamplePageandAutoSuggestBoxSamplePageViewModel,which were mentioned in the
failmessage.This in turn makes the fix straightforward: update the
SampleandSamplePageAttributetypes to use[DynamicallyAccessedMembers]ontheir respective
Typeparameters and properties to preserveconstructors (from the original message) and properties, which almost
certainly will be needed anyway.
(Property preservation is reflexive at this point.)
If you select UI components > AutoSuggestBox in the left-side
tree view, then click the
<>"Show XAML" button, nothing is shownand the following messages are written to the Console:
This is because WPF Attached Properties require use of
[DynamicDependency]to ensure that the required methods areaccessible via Reflection; see also unoplatform/uno.toolkit.ui@3ef6d6ce.
Update all use of
DependencyProperty.RegisterAttached()so thatrequired methods are retained.
Unfortunately, while this fixes the above
failmessages, clickingthe
<>"Show XAML" button still does nothing.Fixing the
<>"Show XAML" button requiresunoplatform/ShowMeTheXAML#30 and replacing the existing
XamlDisplay.Init()invocation withXamlDictionary.Init().Bump to Uno.ShowMeTheXAML 2.0.0-dev0026 to get this fix, and bump
Uno.Sdkwithinglobal.jsonto6.4.58so that things still build.If you select UI components > BreadcrumbBar in the left-side
tree view, then the BreadcrumbBar with Custom DataTemplate
section on the right-hand page doesn't show anything, and Console
output contains:
Fix this by adding
[Microsoft.UI.Xaml.Data.Bindable]toUno.Gallery.Entities.Data.Folder. The use of[Bindable]causesthe
Uno.UI.SourceGenerators.BindableTypeProvidersource generatorto emit
BindableType(…, typeof(Folder))toBindableMetadata.g.cs,which cause all public properties to be added to reflection metadata.
Add
[Bindable]to all other types containing properties withinUno.Gallery.Entities.Data. This fixes a number of other samplesand messages such as:
If you select UI features > Binding in the left-side
tree view, the right-hand panel would be subtly different between
CoreCLR and Native AOT:
The length is: [empty]The length is:Worse, if you enter text into "myTextBox", the bound fields properly
update under CoreCLR. For example, enter "123" into "myTextBox",
and CoreCLR would show:
Under Native AOT, nothing updates.
Console output contains:
Fix this by adding
[Bindable]toBindingSamplePageViewModel.(Which means "just add
[Bindable]!" is quickly becoming my favoriteanswer to everything. Unless the type has
requiredorinit-onlyproperties; see also unoplatform/uno.chefs@06f4f804.)
Continue this pattern: update all types which implement
INotifyPropertyChangedor inherit from a type which implementsINotifyPropertyChangedto have[Bindable]. This fixes thefollowing
failmessages, among others: