-
Notifications
You must be signed in to change notification settings - Fork 557
[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
@@ -110,9 +115,96 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. | |||
<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.
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.