From ee034ff64b2cdbb191bdce45864867ac827c57b7 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 9 Jul 2026 12:55:02 +0200 Subject: [PATCH 1/3] Fix API 37 AppFunctionState metadata collision Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Mono.Android/metadata | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Mono.Android/metadata b/src/Mono.Android/metadata index 9aba17d02a9..834c5577da1 100644 --- a/src/Mono.Android/metadata +++ b/src/Mono.Android/metadata @@ -386,6 +386,8 @@ Android.Graphics.Color Android.Graphics.Color + + + <_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Microsoft.Android.Runtime.NativeAOT.dll" /> diff --git a/build-tools/scripts/Ndk.projitems b/build-tools/scripts/Ndk.projitems index 3dd66262b97..025c62ac4d9 100644 --- a/build-tools/scripts/Ndk.projitems +++ b/build-tools/scripts/Ndk.projitems @@ -24,7 +24,7 @@ android-arm True True - False + True @ANDROID_PACK_VERSION_LONG@ @ANDROID_PACK_VERSION_LONG@ + @MICROSOFT_NETCORE_APP_REF_PACKAGE_VERSION@ <_AndroidLatestStableApiLevel>@ANDROID_LATEST_STABLE_API_LEVEL@ <_AndroidLatestUnstableApiLevel>@ANDROID_LATEST_UNSTABLE_API_LEVEL@ diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets index e145c311485..fb22129ba62 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets @@ -22,7 +22,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. true true - + <_IsPublishing Condition=" '$(_IsPublishing)' == '' ">true @@ -35,6 +35,18 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. true + + + $(MicrosoftNETCoreAppRefPackageVersion) + + <_AndroidNetCoreAppNativeAotKnownRuntimePack Include="@(KnownRuntimePack->WithMetadataValue('Identity', 'Microsoft.NETCore.App')->WithMetadataValue('RuntimePackLabels', 'NativeAOT'))" /> + + + $(MicrosoftNETCoreAppRefPackageVersion) + %(RuntimePackRuntimeIdentifiers);android-arm + + + true @@ -90,9 +102,16 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64 <_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64 + <_NdkAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm' ">arm <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">$(AndroidNdkApiLevel_Arm64) <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">$(AndroidNdkAPiLevel_X64) - <_NdkSysrootAbi>$(_NdkAbi)-linux-android + <_NDKApiLevel Condition=" '$(RuntimeIdentifier)' == 'android-arm' ">$(AndroidNdkApiLevel_Arm) + <_NdkClangPrefix Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64-linux-android + <_NdkClangPrefix Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64-linux-android + <_NdkClangPrefix Condition=" '$(RuntimeIdentifier)' == 'android-arm' ">armv7a-linux-androideabi + <_NdkSysrootAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">aarch64-linux-android + <_NdkSysrootAbi Condition=" '$(RuntimeIdentifier)' == 'android-x64' ">x86_64-linux-android + <_NdkSysrootAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm' ">arm-linux-androideabi <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('windows')) ">windows-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('osx')) ">darwin-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('linux')) ">linux-x86_64 @@ -128,8 +147,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. application. If, for some reason, `clang++` has to be used, `` need to be added to pass `-nostdlib` to it. --> - $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) - $(_NdkAbi)-linux-android$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) + $(_NdkClangPrefix)$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) + $(_NdkClangPrefix)$(_NDKApiLevel)-clang$(_NdkWrapperScriptExt) llvm-objcopy @@ -214,6 +233,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. + <_PrivateBuildTargetAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm' " Include="armeabi-v7a" /> <_PrivateBuildTargetAbi Condition=" '$(RuntimeIdentifier)' == 'android-arm64' " Include="arm64-v8a" /> <_PrivateBuildTargetAbi Condition=" '$(RuntimeIdentifier)' == 'android-x64' " Include="x86_64" /> @@ -361,6 +381,10 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_NativeAotSystemLibraries Include="m" /> <_NativeAotSystemLibraries Include="c" /> + + <_NativeAotLinkLibraries Remove="$(IlcSdkPath)libSystem.Security.Cryptography.Native.Android.a" /> + <_NativeAotLinkLibraries Include="$(_NativeAotRuntimePackNativeDir)libSystem.Security.Cryptography.Native.Android.a" /> + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json index 5de67dcdf60..6a3a324bc61 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Sdk.Android/WorkloadManifest.in.json @@ -15,6 +15,7 @@ "Microsoft.Android.Runtime.CoreCLR.37.android-arm", "Microsoft.Android.Runtime.CoreCLR.37.android-arm64", "Microsoft.Android.Runtime.CoreCLR.37.android-x64", + "Microsoft.Android.Runtime.NativeAOT.37.android-arm", "Microsoft.Android.Runtime.NativeAOT.37.android-arm64", "Microsoft.Android.Runtime.NativeAOT.37.android-x64", "Microsoft.Android.Templates" @@ -91,6 +92,10 @@ "kind": "framework", "version": "@WORKLOAD_VERSION@" }, + "Microsoft.Android.Runtime.NativeAOT.37.android-arm": { + "kind": "framework", + "version": "@WORKLOAD_VERSION@" + }, "Microsoft.Android.Runtime.NativeAOT.37.android-arm64": { "kind": "framework", "version": "@WORKLOAD_VERSION@" diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets index 6c562f5378c..ce4332b110e 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.targets @@ -284,6 +284,7 @@ <_BundledVersionsCacheLines Include="AndroidLatestUnstableApiLevel=$(AndroidLatestUnstableApiLevel)" /> <_BundledVersionsCacheLines Include="DotNetTargetFramework=$(DotNetTargetFramework)" /> <_BundledVersionsCacheLines Include="DotNetTargetFrameworkVersion=$(DotNetTargetFrameworkVersion)" /> + <_BundledVersionsCacheLines Include="MicrosoftNETCoreAppRefPackageVersion=$(MicrosoftNETCoreAppRefPackageVersion)" /> + Replacements="@ANDROID_PACK_VERSION_LONG@=$(AndroidPackVersionLong);@ANDROID_LATEST_STABLE_API_LEVEL@=$(AndroidLatestStableApiLevel);@ANDROID_LATEST_UNSTABLE_API_LEVEL@=$(AndroidLatestUnstableApiLevel);@DOTNET_TARGET_FRAMEWORK@=$(DotNetTargetFramework);@MICROSOFT_NETCORE_APP_REF_PACKAGE_VERSION@=$(MicrosoftNETCoreAppRefPackageVersion)" > false arm64:x86_64 - arm64-v8a:x86_64 + armeabi-v7a:arm64-v8a:x86_64 diff --git a/src/native/native.targets b/src/native/native.targets index 80c87e42131..41c225d349b 100644 --- a/src/native/native.targets +++ b/src/native/native.targets @@ -373,6 +373,14 @@ RuntimePackName="$(_RuntimePackName)" /> + + <_RuntimePackFiles Include="$(XAPackagesDir)\microsoft.netcore.app.runtime.nativeaot.%(AndroidSupportedTargetJitAbi.AndroidRID)\$(MicrosoftNETCoreAppRefPackageVersion)\runtimes\%(AndroidSupportedTargetJitAbi.AndroidRID)\native\libSystem.Security.Cryptography.Native.Android.a" + Condition="Exists('$(XAPackagesDir)\microsoft.netcore.app.runtime.nativeaot.%(AndroidSupportedTargetJitAbi.AndroidRID)\$(MicrosoftNETCoreAppRefPackageVersion)\runtimes\%(AndroidSupportedTargetJitAbi.AndroidRID)\native\libSystem.Security.Cryptography.Native.Android.a')" + AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)" + AndroidRuntime="$(CMakeRuntimeFlavor)" + RuntimePackName="$(_RuntimePackName)" /> + + + + + + + + From 0ec15ee78149e4a092763ea243bb51d62477e9ae Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Fri, 10 Jul 2026 06:57:52 +0200 Subject: [PATCH 3/3] Address android-arm NativeAOT review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f3ad2c76-9fba-41d4-a747-c5602aeae335 --- src/Mono.Android/metadata | 2 - .../Microsoft.Android.Sdk.NativeAOT.targets | 3 +- .../NativeAotBuildTests.cs | 50 +++++++++++++++++++ .../Xamarin.Android.Common.props.in | 1 + src/workloads/workloads.csproj | 6 +-- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/Mono.Android/metadata b/src/Mono.Android/metadata index 834c5577da1..9aba17d02a9 100644 --- a/src/Mono.Android/metadata +++ b/src/Mono.Android/metadata @@ -386,8 +386,6 @@ Android.Graphics.Color Android.Graphics.Color - - + + $(MicrosoftNETCoreAppRefPackageVersion) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/NativeAotBuildTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/NativeAotBuildTests.cs index 1c176bec323..9f1cfab9198 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/NativeAotBuildTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/NativeAotBuildTests.cs @@ -1,3 +1,5 @@ +using System.IO; + using NUnit.Framework; using Xamarin.Android.Tasks; using Xamarin.ProjectTools; @@ -11,6 +13,35 @@ namespace Xamarin.Android.Build.Tests [Category ("Node-2")] public class NativeAotBuildTests : BaseTest { + [Test] + public void RestoreNativeAot_AndroidArmRuntimePack () + { + var proj = new XamarinAndroidApplicationProject { + IsRelease = true, + }; + proj.SetRuntime (AndroidRuntime.NativeAOT); + proj.SetRuntimeIdentifiers (["armeabi-v7a"]); + + using var builder = CreateApkBuilder (); + Assert.IsTrue ( + builder.RunTarget (proj, "Restore"), + "Restore should succeed for android-arm." + ); + + var intermediate = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath); + var assets = File.ReadAllText (Path.Combine (intermediate, "..", "project.assets.json")); + StringAssert.Contains ( + "\"Microsoft.NETCore.App.Runtime.NativeAOT.android-arm\"", + assets, + "Restore should select the android-arm NativeAOT runtime pack." + ); + StringAssert.DoesNotContain ( + "\"Microsoft.NETCore.App.Runtime.NativeAOT.linux-bionic-arm\"", + assets, + "Restore should not fall back to the linux-bionic-arm NativeAOT runtime pack." + ); + } + [Test] public void BuildNativeAot_WithoutNdk () { @@ -44,6 +75,25 @@ public void BuildNativeAot_WithNdkLinker () ); } + [Test] + public void BuildNativeAot_AndroidArm_WithNdkLinker () + { + var proj = new XamarinAndroidApplicationProject { + IsRelease = true, + }; + proj.SetRuntime (AndroidRuntime.NativeAOT); + proj.SetRuntimeIdentifiers (["armeabi-v7a"]); + proj.SetProperty ("_SkipNdkResolution", "false"); + + using var builder = CreateApkBuilder (); + Assert.IsTrue ( + builder.Build (proj, parameters: [ + "_AndroidUseWorkloadNativeLinker=false", + ]), + "android-arm build should succeed with NDK linker." + ); + } + [Test] public void BuildNativeAot_WithoutNdk_WorkloadLinkerDisabled_Fails () { diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in index 881196597c8..99ac3069920 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in @@ -35,6 +35,7 @@ true + @NDK_ARMEABI_V7_API@ @NDK_ARM64_V8A_API@ @NDK_X86_64_API@ diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index ee306c1cd0e..d679797fc8e 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -38,9 +38,9 @@ inside xaprepare. - - - + + +