From 3d461a9f2a2dce782259d59ef07d7956503e15ea Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 24 Aug 2026 15:00:53 -0500 Subject: [PATCH 1/5] [ci] Add Mono MAUI integration build Add a Release MAUI template build that uses Mono to detect regressions such as #12487. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82531bd4-3cc7-485a-8150-57fa0ebe4d04 --- build-tools/automation/azure-pipelines-internal.yaml | 12 ++++++++++++ build-tools/automation/azure-pipelines-public.yaml | 12 ++++++++++++ build-tools/automation/azure-pipelines.yaml | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/build-tools/automation/azure-pipelines-internal.yaml b/build-tools/automation/azure-pipelines-internal.yaml index 257c8faecdd..6ef37aaebbb 100644 --- a/build-tools/automation/azure-pipelines-internal.yaml +++ b/build-tools/automation/azure-pipelines-internal.yaml @@ -934,6 +934,18 @@ stages: xaSourcePath: $(Build.SourcesDirectory)/android displayName: Build MAUI template - Release + - template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml + parameters: + project: $(Build.StagingDirectory)/MauiTestProj/MauiTestProj.csproj + arguments: >- + -f $(DotNetTargetFramework)-android -c Release + -p:UseMonoRuntime=true + -p:_DisableCheckForUnsupportedMonoMobileRuntime=true + --configfile $(Build.SourcesDirectory)/maui/NuGet.config + -bl:$(Build.StagingDirectory)/logs/MauiTestProj-Mono.binlog + xaSourcePath: $(Build.SourcesDirectory)/android + displayName: Build MAUI template - Mono + - task: CopyFiles@2 displayName: copy build logs condition: always() diff --git a/build-tools/automation/azure-pipelines-public.yaml b/build-tools/automation/azure-pipelines-public.yaml index 44eae1ceb96..fcc2347de9d 100644 --- a/build-tools/automation/azure-pipelines-public.yaml +++ b/build-tools/automation/azure-pipelines-public.yaml @@ -620,6 +620,18 @@ stages: xaSourcePath: $(Build.SourcesDirectory)/android displayName: Build MAUI template - Release + - template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml + parameters: + project: $(Build.StagingDirectory)/MauiTestProj/MauiTestProj.csproj + arguments: >- + -f $(DotNetTargetFramework)-android -c Release + -p:UseMonoRuntime=true + -p:_DisableCheckForUnsupportedMonoMobileRuntime=true + --configfile $(Build.SourcesDirectory)/maui/NuGet.config + -bl:$(Build.StagingDirectory)/logs/MauiTestProj-Mono.binlog + xaSourcePath: $(Build.SourcesDirectory)/android + displayName: Build MAUI template - Mono + - template: /build-tools/automation/yaml-templates/run-maui-r2r-helix-matrix.yaml parameters: project: $(Build.StagingDirectory)/MauiTestProj/MauiTestProj.csproj diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 45238bf5ddc..1236e3122a5 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -236,6 +236,18 @@ extends: xaSourcePath: $(Build.SourcesDirectory)/android displayName: Build MAUI template - Release + - template: /build-tools/automation/yaml-templates/run-dotnet-preview.yaml@self + parameters: + project: $(Build.StagingDirectory)/MauiTestProj/MauiTestProj.csproj + arguments: >- + -f $(DotNetTargetFramework)-android -c Release + -p:UseMonoRuntime=true + -p:_DisableCheckForUnsupportedMonoMobileRuntime=true + --configfile $(Build.SourcesDirectory)/maui/NuGet.config + -bl:$(Build.StagingDirectory)/logs/MauiTestProj-Mono.binlog + xaSourcePath: $(Build.SourcesDirectory)/android + displayName: Build MAUI template - Mono + - template: /build-tools/automation/yaml-templates/run-maui-r2r-helix-matrix.yaml@self parameters: project: $(Build.StagingDirectory)/MauiTestProj/MauiTestProj.csproj From 7b8ecf8229089bdf4bf5e27ad9a89a4ad798d2fd Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 24 Aug 2026 18:19:27 -0500 Subject: [PATCH 2/5] [Mono] Preserve JLO marker for satellite assemblies Preserve generated scan-marker metadata for unchanged framework assemblies after trimming so Mono builds do not look for JLO sidecars in NuGet packages. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82531bd4-3cc7-485a-8150-57fa0ebe4d04 --- .../Tests/Xamarin.Android.Build.Tests/BuildTest.cs | 10 +++++++--- .../Xamarin.Android.Common.targets | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 0221e7d0a76..6e18f5297bb 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -2300,8 +2300,9 @@ public void CheckLintResourceFileReferencesAreFixed ([Values (AndroidRuntime.Cor } } - [Test] - public void BuildDoesNotModifyNuGetPackageCache () + [TestCase (AndroidRuntime.CoreCLR)] + [TestCase (AndroidRuntime.MonoVM)] + public void BuildDoesNotModifyNuGetPackageCache (AndroidRuntime runtime) { var proj = new XamarinAndroidApplicationProject { IsRelease = true, @@ -2328,7 +2329,10 @@ public void BuildDoesNotModifyNuGetPackageCache () new Package { Id = "Humanizer.Core.es", Version = "2.14.1" }, }, }; - proj.SetRuntime (AndroidRuntime.CoreCLR); + proj.SetRuntime (runtime); + if (runtime == AndroidRuntime.MonoVM) { + proj.SetProperty ("_DisableCheckForUnsupportedMonoMobileRuntime", "true"); + } proj.SetProperty ("AndroidTypeMapImplementation", "llvm-ir"); proj.SetProperty (KnownProperties.PublishTrimmed, true.ToString ()); proj.MainActivity = proj.DefaultMainActivity diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6c1814efdad..50d8544e561 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1446,6 +1446,12 @@ because xbuild doesn't support framework reference assemblies. <_AndroidLinkNoShrinkOutput Condition=" '%(ResolvedAssemblies.AndroidSkipAssemblyModification)' != 'True' " >$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath) + $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty + $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty <_AndroidAssembliesToLinkNoShrink Include="@(ResolvedAssemblies)" @@ -1525,8 +1531,10 @@ because xbuild doesn't support framework reference assemblies. SourceFiles="@(_AfterILLinkSourceFiles)" TargetName="$(TargetName)"> + + <_AfterILLinkSourceFiles Remove="@(_AfterILLinkSourceFiles)" /> <_AfterILLinkDestFiles Remove="@(_AfterILLinkDestFiles)" /> From 2e8e89ca3584c0c29976233abbf3c4b09c5a295f Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 24 Aug 2026 19:33:27 -0500 Subject: [PATCH 3/5] [Mono] Create scan marker directories Create the intermediate ABI directories before touching scan markers for unchanged assemblies after trimming. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82531bd4-3cc7-485a-8150-57fa0ebe4d04 --- .../Xamarin.Android.Common.targets | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 50d8544e561..1edeb3a7c2f 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1515,6 +1515,7 @@ because xbuild doesn't support framework reference assemblies. Condition=" '$(_AndroidUseMarshalMethods)' != 'True' or !$([System.String]::Copy('%(ResolvedAssemblies.Filename)').ToLowerInvariant().EndsWith('.resources')) " /> <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " Include="@(_AfterILLinkSourceFiles->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" /> <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' == 'True' " Include="@(_AfterILLinkSourceFiles)" /> + <_AndroidScanMarkerFiles Include="@(_AndroidAssembliesToPackageWithoutLinkNoShrink->'%(JavaObjectsXmlFile)')" /> - + + - + <_AfterILLinkSourceFiles Remove="@(_AfterILLinkSourceFiles)" /> <_AfterILLinkDestFiles Remove="@(_AfterILLinkDestFiles)" /> + <_AndroidScanMarkerFiles Remove="@(_AndroidScanMarkerFiles)" /> From 3bdc76066708825f6ac483aba38ee1245ddf3922 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 25 Aug 2026 12:23:18 -0500 Subject: [PATCH 4/5] [Mono] Mark trimmed satellite assemblies unscanned Use the shared scan marker for unprocessed resource assemblies so JLO and typemap consumers do not probe NuGet package directories. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82531bd4-3cc7-485a-8150-57fa0ebe4d04 --- .../Xamarin.Android.Common.targets | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 1edeb3a7c2f..593d639cdca 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1447,10 +1447,10 @@ because xbuild doesn't support framework reference assemblies. Condition=" '%(ResolvedAssemblies.AndroidSkipAssemblyModification)' != 'True' " >$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath) $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty <_AndroidAssembliesToLinkNoShrink @@ -1515,7 +1515,7 @@ because xbuild doesn't support framework reference assemblies. Condition=" '$(_AndroidUseMarshalMethods)' != 'True' or !$([System.String]::Copy('%(ResolvedAssemblies.Filename)').ToLowerInvariant().EndsWith('.resources')) " /> <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " Include="@(_AfterILLinkSourceFiles->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" /> <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' == 'True' " Include="@(_AfterILLinkSourceFiles)" /> - <_AndroidScanMarkerFiles Include="@(_AndroidAssembliesToPackageWithoutLinkNoShrink->'%(JavaObjectsXmlFile)')" /> + <_AndroidScanMarkerFiles Include="@(ResolvedAssemblies->'%(JavaObjectsXmlFile)')" Condition=" '%(ResolvedAssemblies.JavaObjectsXmlFile)' != '' " /> Date: Tue, 25 Aug 2026 13:12:17 -0500 Subject: [PATCH 5/5] [Mono] Align trimmed marker conditions Do not advertise scan markers for trimmed satellite assemblies in the trimmable typemap path, where no marker producer runs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 82531bd4-3cc7-485a-8150-57fa0ebe4d04 --- .../Xamarin.Android.Common.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 593d639cdca..b6c046b89da 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1447,10 +1447,10 @@ because xbuild doesn't support framework reference assemblies. Condition=" '%(ResolvedAssemblies.AndroidSkipAssemblyModification)' != 'True' " >$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath) $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty $(MonoAndroidIntermediateAssemblyDir)%(DestinationSubDirectory)%(Filename).scan.empty <_AndroidAssembliesToLinkNoShrink