-
Notifications
You must be signed in to change notification settings - Fork 560
[native] NativeAOT runtime #10461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[native] NativeAOT runtime #10461
Conversation
443bfb4
to
03d77e5
Compare
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
03d77e5
to
04ca2d9
Compare
Requested feature addition: CoreCLR has logic to use
It would be handy if similar integration could be done with NativeAOT, such that |
@jonpryor I plan to add support for this, definitely. It'll be the same mechanism as with CoreCLR, just need to implement a bit more things before that |
src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs
Show resolved
Hide resolved
@grendello @jonathanpeppers should I close #10402 if this is intended to replace it? |
@jkoritzinsky no, please keep it open. I'm not going to put everything in this PR that's in #10402. Once this one is done, you can rebase yours and apply the remaining changes + finetuning + whatnot. I should be done with this PR next week (need to add two more things) |
bb04b1e
to
e6d636a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NativeAOT test on Windows is failing with:
(_CollectAssembliesToCompress target) ->
C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Sdk.Windows\36.0.0-ci.dev-grendel-naot-runtime.323\tools\Xamarin.Android.Common.targets(2258,3): error XACAF7009: System.InvalidOperationException: Assembly compression info not found for key '__CompressedAssembliesInfo:C:\a\_work\1\a\TestRelease\09-10_14.27.54\temp\NativeAOT\Hello.csproj'. Compression will not be performed. [C:\a\_work\1\a\TestRelease\09-10_14.27.54\temp\NativeAOT\Hello.csproj]
C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Sdk.Windows\36.0.0-ci.dev-grendel-naot-runtime.323\tools\Xamarin.Android.Common.targets(2258,3): error XACAF7009: at Xamarin.Android.Tasks.CollectAssemblyFilesToCompress.GetCompressedAssemblyInfo() [C:\a\_work\1\a\TestRelease\09-10_14.27.54\temp\NativeAOT\Hello.csproj]
C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Sdk.Windows\36.0.0-ci.dev-grendel-naot-runtime.323\tools\Xamarin.Android.Common.targets(2258,3): error XACAF7009: at Xamarin.Android.Tasks.CollectAssemblyFilesToCompress.RunTask() [C:\a\_work\1\a\TestRelease\09-10_14.27.54\temp\NativeAOT\Hello.csproj]
C:\a\_work\1\s\bin\Release\dotnet\packs\Microsoft.Android.Sdk.Windows\36.0.0-ci.dev-grendel-naot-runtime.323\tools\Xamarin.Android.Common.targets(2258,3): error XACAF7009: at Microsoft.Android.Build.Tasks.AndroidTask.Execute() [C:\a\_work\1\a\TestRelease\09-10_14.27.54\temp\NativeAOT\Hello.csproj]
I don't see any new RegisterTaskObject()
calls.
So, is the problem specific to Windows? Or maybe the test is doing multiple RIDs?
...in.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
Outdated
Show resolved
Hide resolved
<!-- Passes linked assemblies to outer MSBuild tasks/targets --> | ||
<ResolvedFileToPublish Include="@(IlcCompileInput);@(_AndroidILLinkAssemblies)" RuntimeIdentifier="$(RuntimeIdentifier)" /> | ||
<!-- Include libc++ --> | ||
<ResolvedFileToPublish Include="$(_NdkSysrootDir)libc++_shared.so" RuntimeIdentifier="$(RuntimeIdentifier)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be removed? Are we statically linking libc++
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're not right now because NativeAOT has a compatibility library that conflicts with static libc++
. I want to explore a fix for this in a separate PR, since this one is too big already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it makes sense to split that off into separate PR. I suppose you can remove the shim libc++
from the list and then add the real one instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to keep both references to libc++_shared.so
in this PR as we both need to link against it (the <LinkerArg>
item) and package it (the ResolvedFileToPublish
item)
if (gref_gc_threshold != int.MaxValue) { | ||
gref_gc_threshold = checked((gref_gc_threshold * 9) / 10); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this taking 90% of this number for all runtimes? Do we need this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other runtimes set gref_gc_threshold
through different code path but it's still the same value (90% of the max GREF count).
This mostly seems to work, except few build issues and excessive logging. When doing
Since NativeAOT doesn't operate with assemblies it seems safe to workaround it with When doing multi-RID builds (again, default) I constantly got a variation of this error (for either RID at random):
To get past that I used The startup took well over a minute and the whole log was spammed with the following:
Presumably the slow startup was caused just by the logging but it needs to be verified. Experiments with the previous PR showed similar behavior due to incorrectly set |
493cbd8
to
96113be
Compare
The problem was Debug vs Release. I tested only in the former and disabled only part of compressed assembly support. It should work now for Release too. |
The GREF threshold initialization still seems to be wrong:
Essentially every allocation of bridge object triggers a GC. Probably a missing call to |
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time, we've decided to introduce a new stage to build and run these unit tests within an Android+NativeAOT environment. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
Builds, installs, does nothing yet.
Linking seems to work, not tested yet
NativeAOT sample now links without errors about missing symbols (added linker options for it to fail if missing symbols are detected)
Disable attempts to collect assemblies for compression to avoid this error: D:\dotnet-android\android\bin\Debug\dotnet\packs\Microsoft.Android.Sdk.Windows\36.0.0-ci.dev-grendel-naot-runtime.323\tools\Xamarin.Android.Common.targets(2258,3): error XACAF7009: System.InvalidOperationException: Assembly compression info not found for key '__CompressedAssembliesInfo:D:\emcli ent\MailClient.Mobile\MailClient.Mobile.Android\MailClient.Mobile.Android.csproj'. Compression will not be perform ed. at Xamarin.Android.Tasks.CollectAssemblyFilesToCompress.GetCompressedAssemblyInfo() at Xamarin.Android.Tasks.CollectAssemblyFilesToCompress.RunTask() at Microsoft.Android.Build.Tasks.AndroidTask.Execute()
251297f
to
68b9a88
Compare
// TODO: this shouldn't be public | ||
public class AndroidObjectReferenceManager : JniRuntime.JniObjectReferenceManager { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only thing we'll need to fix ASAP next week.
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
Context: #10461 A follow up to #10461 which adds some more compatibility with the "standard" MonoVM and CoreCLR runtime hosts, namely: * Support for setting environment variables via the environment file (`<AndroidEnvironment>` MSBuild item) * Support for setting **local** (that is, application level, not system level) system properties In addition to the above, it makes NativeAOT use static libc++ instead of the shared one, which not only shrinks the package size (`libc++_shared.so` is around 9mb), but it also makes startup slightly faster.
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. Finally, .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Note: Do *not* make Release-config apps [Debuggable][2] under .NET 10 Preview 7 or earlier; you will run into [dotnet/java-interop@90ac202e][3]. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Update `UnitTestsControl.cs` to provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 The problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist* (it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`). Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to the above two mentioned exceptions. 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Update `UnitTestsControl.cs` to provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 The problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist* (it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`). Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to the above two mentioned exceptions. 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Update `UnitTestsControl.cs` to provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 The problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist* (it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`). Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to the above two mentioned exceptions. These are ignored via: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Update `UnitTestsControl.cs` to provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 The problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist* (it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`). Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to the above two mentioned exceptions. These are ignored via: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Update `UnitTestsControl.cs` to provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 The problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist* (it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`). Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to the above two mentioned exceptions. These are ignored via: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. These are ignored via: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] Update `UnitTestsControl.cs` to try to work around NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Additionally, if a `TargetInvocationException` is thrown when the the method arguments count and parameters count match, throw an `AssertInconclusiveException`. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into two major categories: 1. Failures that don't make sense, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. These are ignored via: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] Update `UnitTestsControl.cs` to try to work around NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many (many!) tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Additionally, if a `TargetInvocationException` is thrown when the the method arguments count and parameters count match, throw an `AssertInconclusiveException`. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`, which fails: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 or: System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`, which fails: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 or: System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`, which fails: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 or: System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
…droid Context: #21256 / 52a6f3e Context: dotnet/android#10461 Context: dotnet/android#10457 Context: dotnet/android#10463 Context: AwesomeAssertions/AwesomeAssertions#290 #21256 added support for building with .NET 10, and one of the new features in .NET 10 is that Android has (very!) preliminary preview support for [NativeAOT][0]. As building `SamplesApp.Skia.netcoremobile.csproj` with NativeAOT takes a significant amount of time and disk space, we've decided to introduce a new `Tests - Android+NativeAOT Skia` stage to build and run these unit tests within an Android+NativeAOT environment. To help reduce disk usage, after building the `.apk` we delete the `obj` directory. Update `android-run-skia-runtime-tests.sh` to always create the `$(build.sourcesdirectory)/build/uitests-failure-results` path before existing with an error, as failure to do so means that the `PublishBuildArtifacts@1` YAML task fails: ##[error]Publishing build artifacts failed with an error: Not found PathtoPublish: /agent/_work/1/s/build/uitests-failure-results which in turn means subsequent `DownloadBuildArtifacts@0` / **Download previous test runs failed tests** steps *also* always fail: ##[error]Artifact uitests-android-nativeaot-failure-results not found for build 174635. Please ensure you have published artifacts in any previous phases of the current build. Update `ApplicationData.GetRoamingFolder()` to explicitly create `Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)`. (Apparently this isn't created by default under NativeAOT?) This avoids a startup assertion: I NativeAotFromAndroid: App failed to initialize: System.IO.DirectoryNotFoundException: IO_PathNotFound_Path, /data/user/0/uno.platform.samplesapp.skia/files/.config/b63c4306-f361-42d0-bc1d-5be385a95c78.txt I NativeAotFromAndroid: at System.IO.FileSystem.DeleteFile(String) + 0xe7 I NativeAotFromAndroid: at SamplesApp.App.<AssertApplicationData>g__AssertCanCreateFile|32_3(StorageFolder) + 0x10c I NativeAotFromAndroid: at SamplesApp.App.AssertApplicationData() + 0xa5 I NativeAotFromAndroid: at SamplesApp.App..ctor() + 0x2a3 I NativeAotFromAndroid: at SamplesApp.Droid.Application.<>c.<.ctor>b__0_0() + 0x18 I NativeAotFromAndroid: at Microsoft.UI.Xaml.NativeApplication.<OnActivityStarted>b__7_0() + 0x12 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.<Run>g__CreateApp|2_10(ApplicationInitializationCallbackParams _) + 0xf I NativeAotFromAndroid: at Microsoft.UI.Xaml.Application.StartPartial(ApplicationInitializationCallback callback) + 0xb5 I NativeAotFromAndroid: at Uno.UI.Runtime.Skia.Android.AndroidHost.Run() + 0x306 Enable NativeAOT builds by updating `SamplesApp.Skia.netcoremobile.csproj` to set the [`$(PublishAot)`][1] property to the `$(SkiaPublishAot)` MSBuild property. This allows us to build a single project for NativeAOT -- `SamplesApp.Skia.netcoremobile.csproj` -- *without* trying to build every referenced project for NativeAOT, which is what happens if you instead try `dotnet publish -p:PublishAot=true …`, which fails: % dotnet build -c Release -p:PublishAot=true src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj -bl … …/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(121,5): error NETSDK1207: Ahead-of-time compilation is not supported for the target framework. % dotnet publish src/SamplesApp/SamplesApp.Skia.netcoremobile/SamplesApp.Skia.netcoremobile.csproj \ -c Release -r android-x64 -f net10.0-android -p:UnoTargetFrameworkOverride=net10.0-android -p:SkiaPublishAot=true -bl # succeeds… after 15 minutes… This also requires updating `$(NoWarn)` to ignore the hundreds of IL trimmer warnings. We're just trying to see where things stand for now. Additionally, we need to publish with `-r android-x64` in order to avoid the build error: …/Microsoft.NETCore.Native.Publish.targets(92,5): error MSB3030: Could not copy the file "bin/Release/net10.0-android/native/SamplesApp.so" because it was not found. Because it's `bin/Release/net10.0-android/android-{arm64,x64}/native/SamplesApp.so`! Oddly, using `-r android-x64` still results in *both* ABIs being included, which appears to be a unoplatform/uno "bug": % unzip -l src/SamplesApp/SamplesApp.Skia.netcoremobile/bin/Release/net10.0-android/android-x64/publish/uno.platform.samplesapp.skia-Signed.apk | grep SamplesApp.so 763563120 08-28-2025 19:47 lib/x86_64/libSamplesApp.so 757982224 08-28-2025 19:48 lib/arm64-v8a/libSamplesApp.so The need for `-r android-x64` may be related to dotnet/android#10457. .NET Crypto support isn't propertly initialized in Android+NativeAOT apps in .NET 10 RC1; see dotnet/android#10463. This may be fixed in dotnet/android#10461, but in the meantime we can manually call `AndroidCryptoNative_InitLibraryOnLoad()` so that methods such as `SHA1.Create()` won't throw. Exclude tests which don't pass under NativeAOT. These fall into three major categories: 1. Failures that don't make sense, likely due to unknown bugs within the NativeAOT toolchain itself, failing due to `TargetParameterCountException` or `InvalidOperationException` described below. Some of these are worked around (see below), while others are ignored via e.g.: [Ignore("DataRowAttribute.GetData() wraps data in an extra array under NativeAOT; not yet understood why.")] 2. Failures which are due to `AwesomeAssertions` using `MethodInfo.MakeGenericMethod()`; see AwesomeAssertions/AwesomeAssertions#290: Unhandled exception. System.NotSupportedException: 'AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.HandleImpl[System.Int32](AwesomeAssertions.Equivalency.Steps.EnumerableEquivalencyValidator,System.Object[],System.Collections.Generic.IEnumerable`1[System.Int32])' is missing native code. MethodInfo.MakeGenericMethod() is not compatible with AOT compilation. Inspect and fix AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility at System.Reflection.Runtime.MethodInfos.RuntimeNamedMethodInfo`1.GetUncachedMethodInvoker(RuntimeTypeInfo[], MemberInfo) + 0x2a at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x3f at AwesomeAssertions.Equivalency.Steps.GenericEnumerableEquivalencyStep.Handle(Comparands, IEquivalencyValidationContext, IValidateChildNodeEquivalency) + 0x21a at AwesomeAssertions.Equivalency.EquivalencyValidator.TryToProveNodesAreEquivalent(Comparands, IEquivalencyValidationContext) + 0x129 at AwesomeAssertions.Equivalency.EquivalencyValidator.AssertEquality(Comparands, EquivalencyValidationContext) + 0x43 at AwesomeAssertions.Collections.GenericCollectionAssertions`3.BeEquivalentTo[TExpectation](IEnumerable`1, Func`2, String, Object[]) + 0x1f9 Basically, the `.BeBeEquivalentTo()` extension method cannot currently work in NativeAOT environments. These are ignored via: [Ignore(".BeEquivalentTo() unsupported under NativeAOT; see: AwesomeAssertions/AwesomeAssertions#290")] 3. Other limitations within the NativeAOT environment. For example, Android+NativeAOT does not yet have a GC bridge, meaning every `Java.Lang.Object` subclass instance is *never* collected by the GC unless explicitly `.Dispose()`d Update `UnitTestsControl.cs` to try to work around some NativeAOT "weirdness" and provide better error messages when tests fail in certain scenarios. Previously, many tests would fail with one of: System.Reflection.TargetParameterCountException: Arg_ParmCnt at System.Reflection.DynamicInvokeInfo.ThrowForArgCountMismatch() + 0x83 at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x136 at Internal.Reflection.Execution.MethodInvokers.InstanceMethodInvoker.Invoke(Object, Object[], BinderBundle, Boolean) + 0x4f at Internal.Reflection.Core.Execution.MethodBaseInvoker.Invoke(Object, Object[], Binder, BindingFlags, CultureInfo) + 0x48 at System.Reflection.Runtime.MethodInfos.RuntimeMethodInfo.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) + 0x70 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x4b9 or: System.InvalidOperationException: Missing parameter does not have default value at Uno.UI.Samples.Tests.UnitTestsControl.ExpandArgumentsWithDefaultValues(Object[] methodArguments, ParameterInfo[] methodParameters) + 0x138 at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_4.<<ExecuteTestsForInstance>b__12>d.MoveNext() + 0x92 --- End of stack trace from previous location --- at Uno.UI.Samples.Tests.UnitTestsControl.<>c__DisplayClass67_2.<<ExecuteTestsForInstance>g__InvokeTestMethod|5>d.MoveNext() + 0x549 A problem is that the reported test that was failing would be reported as e.g. `When_Add_Remove(System.Object[])`, which is a test method which *does not exist*; it's actually `When_Add_Remove(object, int, LeakTestStyles, RuntimeTestPlatforms)`. Additionally, which parameter doesn't have a default value? Or how does the parameter count not match? Or… An intermediate form of this commit would wrap the `TargetParameterCountException` in an `InvalidOperationException`, resulting in messages such as: System.InvalidOperationException: Exception thrown while invoking Uno.UI.Tests.Windows_Globalization.Given_NumeralSystemTranslator.When_NumeralSystemIsMtei(System.String, System.String) with arguments { System.Object[]{ 1 as System.String, ꯱ as System.String } }. ---> System.Reflection.TargetParameterCountException: Parameter count mismatch. Note that `When_NumeralSystemIsMtei(System.String, System.String)` takes two arguments, but it's given *one* argument with value `{{ System.Object[]{ 1 as System.String, ꯱ as System.String } }}`, i.e. *the values are there*, just "wrapped" in an extra array. Update `UnitTestsControl.InvokeTestMethod()` to always call `ExpandArgumentsWithDefaultValues()` as part of test method invocation, so that we have a centralized place to look for such "extra array wrapping". Update `ExpandArgumentsWithDefaultValues()` so that if it encounters an array for a parameter type which isn't an array, the array is expanded as additional arguments. Log various "weird" scenarios via `Console.WriteLine()` to make it easier to get a "complete" listing of such failing methods by using `adb logcat` output. TODO? the migration to AwesomeAssertions in 80c0705 results in some "bizarre" failure messages, e.g. Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException: Expected value to be less than or equal to 81 because TextBox/SingleTextBox;Microsoft.UI.Xaml.VisualStateManager;Microsoft.UI.Xaml.Controls.Grid;…;ElementStub/HorizontalScrollBar;… which is *truncated* at *4000* characters. *Something* is wonky there. [0]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/ [1]: https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/?tabs=windows%2Cnet8#publish-native-aot-using-the-cli [2]: https://developer.android.com/guide/topics/manifest/application-element#debug [3]: dotnet/java-interop@90ac202
Fixes: #10455
Implements a minimal Android host for NativeAOT applications. The goal is to create
a runtime environment that is as compatible with Xamarin.Android / .NET for Android
applications using MonoVM or CoreCLR as possible. This PR implements the very basics:
<AndroidEnvironment>
)An important element that's currently missing is linking
libc++
statically into the runtime, instead we include the sharedlibc++
from the NDK. The reason for this is thatNativeAOT build task references a compatibility C++ library which produces conflicts with
the static
libc++
one when attempting to link. This issue will be fixed in a separatePR.