From 79aa279e9e1b16af8b0ee137be124b8ac955343c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 19 Aug 2026 12:59:06 -0500 Subject: [PATCH 1/2] Add NativeAOT custom configuration device test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e48442c2-2acb-4228-9eec-4b7930738a0f --- .../Tests/InstallAndRunTests.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 93e64d8656b..a8b4631707f 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -2754,6 +2754,44 @@ public static void logEvent(String eventName) {{ RunProjectAndAssert (proj, builder); } + [Test] + public void NativeAOTCustomReleaseConfiguration ([Values] bool publish) + { + const string configuration = "AppStore"; + var proj = new XamarinAndroidApplicationProject (releaseConfigurationName: configuration) { + IsRelease = true, + }; + proj.SetRuntime (AndroidRuntime.NativeAOT); + var rid = MonoAndroidHelper.AbiToRid (DeviceAbi); + proj.SetProperty ("RuntimeIdentifier", rid); + proj.SetProperty (proj.ReleaseProperties, "Optimize", "true"); + proj.SetProperty (proj.ReleaseProperties, "DebugType", "None"); + + using var builder = CreateApkBuilder (); + builder.Save (proj); + + var dotnet = new DotNetCLI (Path.Combine (Root, builder.ProjectDirectory, proj.ProjectFilePath)); + var arguments = new [] { "-c", configuration }; + var succeeded = publish + ? dotnet.Publish (runtimeIdentifier: rid, msbuildArguments: arguments) + : dotnet.Build (runtimeIdentifier: rid, msbuildArguments: arguments); + Assert.IsTrue (succeeded, $"`dotnet {(publish ? "publish" : "build")} -c {configuration}` should succeed"); + + var outputDirectory = Path.Combine (Root, builder.ProjectDirectory, proj.OutputPath, rid); + if (publish) { + outputDirectory = Path.Combine (outputDirectory, "publish"); + } + var apk = Path.Combine (outputDirectory, $"{proj.PackageName}-Signed.apk"); + FileAssert.Exists (apk); + Assert.AreEqual ("Success", RunAdbCommand ($"install -r \"{apk}\"").Trim (), "APK should install."); + + ClearAdbLogcat (); + StartActivityAndAssert (proj); + Assert.IsTrue (WaitForActivityToStart (proj.PackageName, "MainActivity", + Path.Combine (Root, builder.ProjectDirectory, "logcat.log"), ActivityStartTimeoutInSeconds), + "Activity should have started."); + } + [Test] public void NativeAOTSample () { From d9caa6c2e52c70e37e622ff015a55790f0214691 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 21 Aug 2026 12:17:55 -0500 Subject: [PATCH 2/2] Fix NativeAOT custom configurations Select NativeAOT for publish or optimized builds while keeping unoptimized Debug builds on CoreCLR. Resolve NativeAOT runtime-pack libraries by optimization flavor instead of the project configuration name. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e48442c2-2acb-4228-9eec-4b7930738a0f --- .../Microsoft.Android.Sdk.DefaultProperties.targets | 5 +++-- .../targets/Microsoft.Android.Sdk.NativeAOT.targets | 10 +++++++--- .../TrimmableTypeMapBuildTests.cs | 2 +- .../Tests/InstallAndRunTests.cs | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets index f03550603d9..cc5dc0b262a 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets @@ -29,8 +29,9 @@ See: https://github.com/dotnet/sdk/blob/955c0fc7b06e2fa34bacd076ed39f61e4fb61716/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L16 --> <_GetChildProjectCopyToPublishDirectoryItems>false - <_AndroidRuntime Condition=" '$(PublishAot)' == 'true' ">NativeAOT - <_AndroidRuntime Condition=" '$(PublishAot)' != 'true' and '$(UseMonoRuntime)' == 'true' ">MonoVM + + <_AndroidRuntime Condition=" '$(_AndroidRuntime)' == '' and '$(PublishAot)' == 'true' and ('$(_IsPublishing)' == 'true' or '$(Optimize)' == 'true') ">NativeAOT + <_AndroidRuntime Condition=" '$(_AndroidRuntime)' == '' and '$(UseMonoRuntime)' == 'true' ">MonoVM <_AndroidRuntime Condition=" '$(_AndroidRuntime)' == '' ">CoreCLR true 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 9ec28273a23..3a89f1c582f 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 @@ -100,6 +100,10 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('windows')) ">windows-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('osx')) ">darwin-x86_64 <_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('linux')) ">linux-x86_64 + + <_AndroidNativeAotRuntimeFlavor Condition=" '$(Optimize)' == 'true' ">release + <_AndroidNativeAotRuntimeFlavor Condition=" '$(_AndroidNativeAotRuntimeFlavor)' == '' ">debug + <_AndroidNativeAotRuntimeLibraryName>libnaot-android.$(_AndroidNativeAotRuntimeFlavor)-static-$(_AndroidNativeAotRuntimeFlavor) - <_NdkLibs Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libnaot-android.$(Configuration.ToLower())-static-$(Configuration.ToLower())'))" /> + <_NdkLibs Include="@(RuntimePackAsset->WithMetadataValue('Filename', '$(_AndroidNativeAotRuntimeLibraryName)'))" /> <_NdkLibs Include="$(_NdkSysrootDir)libc++_static.a" /> @@ -278,7 +282,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. _RuntimePackLibraryDirectory is not populated for NativeAOT, so derive the path from the libnaot-android RuntimePackAsset item. --> - <_NativeAotRuntimePackAsset Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libnaot-android.$(Configuration.ToLower())-static-$(Configuration.ToLower())'))" /> + <_NativeAotRuntimePackAsset Include="@(RuntimePackAsset->WithMetadataValue('Filename', '$(_AndroidNativeAotRuntimeLibraryName)'))" /> <_NativeAotRuntimePackNativeDir>@(_NativeAotRuntimePackAsset->'%(RootDir)%(Directory)') @@ -334,7 +338,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. - <_NativeAotLinkLibraries Include="@(RuntimePackAsset->WithMetadataValue('Filename', 'libnaot-android.$(Configuration.ToLower())-static-$(Configuration.ToLower())'))" /> + <_NativeAotLinkLibraries Include="@(RuntimePackAsset->WithMetadataValue('Filename', '$(_AndroidNativeAotRuntimeLibraryName)'))" /> <_NativeAotLinkLibraries Include="$(_NativeAotRuntimePackNativeDir)libc++_static.a" /> <_NativeAotLinkLibraries Include="$(_NativeAotRuntimePackNativeDir)libc++abi.a" /> diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs index 769a2e4992b..368b4f3dc92 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs @@ -51,7 +51,7 @@ public void Build_PublishAotProject_UsesTrimmableTypeMapForCoreClrDebug () proj.SetProperty ("NativeCompilationDuringPublish", "false"); using var builder = CreateApkBuilder (); - Assert.IsTrue (builder.Build (proj, parameters: [ "_AndroidRuntime=CoreCLR" ]), "Build should have succeeded."); + Assert.IsTrue (builder.Build (proj), "Build should have succeeded."); var intermediateDir = builder.Output.GetIntermediaryPath ("typemap"); AssertTrimmableTypeMapOutputs (intermediateDir); diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index a8b4631707f..c4a5a2feed5 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -2783,7 +2783,7 @@ public void NativeAOTCustomReleaseConfiguration ([Values] bool publish) } var apk = Path.Combine (outputDirectory, $"{proj.PackageName}-Signed.apk"); FileAssert.Exists (apk); - Assert.AreEqual ("Success", RunAdbCommand ($"install -r \"{apk}\"").Trim (), "APK should install."); + Assert.That (RunAdbCommand ($"install -r \"{apk}\"").Trim (), Does.EndWith ("Success"), "APK should install."); ClearAdbLogcat (); StartActivityAndAssert (proj);