From ebcf2bde7ea2a743d8959d11311892dd16437832 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 2 Apr 2026 17:27:51 +0200 Subject: [PATCH 1/2] Fix XALNS7015: run _LinkAssembliesNoShrink before R2R in non-trimmed builds Move _LinkAssembliesNoShrink from the outer build into the inner (per-RID) build using BeforeTargets="_PrepareForReadyToRunCompilation". This ensures assembly modifications (FixAbstractMethods, AddKeepAlives, FindJavaObjects, etc.) operate on pure IL assemblies BEFORE crossgen2 creates R2R images, preventing Mono.Cecil from attempting to write mixed-mode assemblies. Changes: - Rewrite _LinkAssembliesNoShrink to run in the inner build, consuming @(ResolvedFileToPublish) instead of @(ResolvedAssemblies), writing to an intermediate linked-noshrink/ directory - Properly classify framework vs user assemblies by known names (matching the trimmed path in _AfterILLinkAdditionalSteps) - Update ResolvedFileToPublish so R2R and publish consume modified copies - Simplify _PrepareAssemblies: populate _ResolvedAssemblies unconditionally from @(ResolvedAssemblies) (no longer redirect through intermediate dir) - Extend _CopySidecarXmlToAssemblyPaths to handle both trimmed (linked/) and non-trimmed (android/linked-noshrink/) sidecar XML files - Remove _LinkAssembliesNoShrink from _LinkAssemblies DependsOnTargets - Remove Assert.Ignore workarounds in BuildTest.SimilarAndroidXAssemblyNames and LinkerTests.AndroidAddKeepAlives for CoreCLR non-trimmed Release builds Fixes: https://github.com/dotnet/android/issues/11025 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...oft.Android.Sdk.AssemblyResolution.targets | 14 +- .../Xamarin.Android.Build.Tests/BuildTest.cs | 15 -- .../Tasks/LinkerTests.cs | 16 -- .../Xamarin.Android.Common.targets | 143 +++++++++++++----- 4 files changed, 112 insertions(+), 76 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index 0d0a212b938..ac974bcd327 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -206,20 +206,18 @@ _ResolveAssemblies MSBuild target. + + <_ResolvedAssemblies Include="@(ResolvedAssemblies)" /> + <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" /> + <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" /> + <_ResolvedSymbols Include="@(ResolvedSymbols)" /> + - <_ResolvedAssemblies Include="@(ResolvedAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> - <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> - <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> - <_ResolvedSymbols Include="@(ResolvedSymbols->'$(MonoAndroidIntermediateAssemblyDir)%(DestinationSubPath)')" Condition=" '%(DestinationSubPath)' != '' " /> <_ShrunkAssemblies Include="@(_ResolvedAssemblies)" /> <_ShrunkUserAssemblies Include="@(_ResolvedUserAssemblies)" /> <_ShrunkFrameworkAssemblies Include="@(_ResolvedFrameworkAssemblies)" /> - <_ResolvedAssemblies Include="@(ResolvedAssemblies)" /> - <_ResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" /> - <_ResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" /> - <_ResolvedSymbols Include="@(ResolvedSymbols)" /> <_ShrunkFrameworkAssemblies Include="@(_ShrunkAssemblies)" Condition=" '%(_ShrunkAssemblies.FrameworkAssembly)' == 'true' " 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 a8a90ae9ff3..3e8c108104e 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 @@ -2178,21 +2178,6 @@ public void CheckLintResourceFileReferencesAreFixed ([Values] AndroidRuntime run // TODO: [TestCase (false, AndroidRuntime.NativeAOT)] public void SimilarAndroidXAssemblyNames (bool publishTrimmed, AndroidRuntime runtime) { - if (!publishTrimmed && runtime == AndroidRuntime.CoreCLR) { - // This currently fails with the following exception: - // - // error XALNS7015: System.NotSupportedException: Writing mixed-mode assemblies is not supported - // at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters) - // at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters) - // at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters) - // at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters) - // at Xamarin.Android.Tasks.SaveChangedAssemblyStep.ProcessAssembly(AssemblyDefinition assembly, StepContext context) in src/Xamarin.Android.Build.Tasks/Tasks/AssemblyModifierPipeline.cs:line 197 - // at Xamarin.Android.Tasks.AssemblyPipeline.Run(AssemblyDefinition assembly, StepContext context) in src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPipeline.cs:line 26 - // at Xamarin.Android.Tasks.AssemblyModifierPipeline.RunPipeline(AssemblyPipeline pipeline, ITaskItem source, ITaskItem destination) in src/Xamarin.Android.Build.Tasks/Tasks/AssemblyModifierPipeline.cs:line 175 - Assert.Ignore ("CoreCLR: fails because of a Mono.Cecil lack of support"); - return; - } - bool aotAssemblies = runtime == AndroidRuntime.MonoVM && publishTrimmed; var proj = new XamarinAndroidApplicationProject { IsRelease = true, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs index 1c995304248..a26a8ec2e0f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/LinkerTests.cs @@ -469,22 +469,6 @@ public void AndroidAddKeepAlives (bool isRelease, bool setAndroidAddKeepAlivesTr return; } - if (runtime == AndroidRuntime.CoreCLR && isRelease && !setAndroidAddKeepAlivesTrue && setLinkModeNone && shouldAddKeepAlives) { - // This currently fails with the following exception: - // - // error XALNS7015: System.NotSupportedException: Writing mixed-mode assemblies is not supported - // at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters) - // at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters) - // at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters) - // at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters parameters) - // at Xamarin.Android.Tasks.SaveChangedAssemblyStep.ProcessAssembly(AssemblyDefinition assembly, StepContext context) in src/Xamarin.Android.Build.Tasks/Tasks/AssemblyModifierPipeline.cs:line 197 - // at Xamarin.Android.Tasks.AssemblyPipeline.Run(AssemblyDefinition assembly, StepContext context) in src/Xamarin.Android.Build.Tasks/Utilities/AssemblyPipeline.cs:line 26 - // at Xamarin.Android.Tasks.AssemblyModifierPipeline.RunPipeline(AssemblyPipeline pipeline, ITaskItem source, ITaskItem destination) in src/Xamarin.Android.Build.Tasks/Tasks/AssemblyModifierPipeline.cs:line 175 - // at Xamarin.Android.Tasks.AssemblyModifierPipeline.RunTask() in src/Xamarin.Android.Build.Tasks/Tasks/AssemblyModifierPipeline.cs:line 123 - Assert.Ignore ("CoreCLR: fails because of a Mono.Cecil lack of support"); - return; - }; - var proj = new XamarinAndroidApplicationProject { IsRelease = isRelease, OtherBuildItems = { diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6d187855e88..99ce63468c2 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1419,18 +1419,62 @@ because xbuild doesn't support framework reference assemblies. - + + + + <_LinkAssembliesNoShrinkDir>$(IntermediateOutputPath)android\linked-noshrink\ + + + + + + + + - - <_AllResolvedAssemblies Include="@(ResolvedAssemblies)" /> + <_LinkNoShrinkAllAssemblies Include="@(ResolvedFileToPublish)" Condition=" '%(Extension)' == '.dll' "> + $(_LinkAssembliesNoShrinkAbi) + + + + + + <_LinkNoShrinkAllAssemblies + Update="@(_LinkNoShrinkAllAssemblies)" + Condition=" '%(Filename)' == '$(TargetName)' " + HasMonoAndroidReference="true" /> + + + + + <_LinkNoShrinkUserAssemblies Include="@(_LinkNoShrinkAllAssemblies)" + Condition=" '%(Filename)' != 'Mono.Android' and '%(Filename)' != 'Mono.Android.Export' and '%(Filename)' != 'Mono.Android.Runtime' and '%(Filename)' != 'Java.Interop' " /> - - + + + + + + + + + + + + + + - + <_LinkNoShrinkAllAssemblies Remove="@(_LinkNoShrinkAllAssemblies)" /> + <_LinkNoShrinkUserAssemblies Remove="@(_LinkNoShrinkUserAssemblies)" /> @@ -1595,23 +1655,27 @@ because xbuild doesn't support framework reference assemblies. + Condition=" '$(_ComputeFilesToPublishForRuntimeIdentifiers)' != 'true' "> + + <_SidecarSubDir Condition=" '$(PublishTrimmed)' == 'true' ">linked\ + <_SidecarSubDir Condition=" '$(PublishTrimmed)' != 'true' ">android\linked-noshrink\ + - <_SidecarLinkedDir Condition=" $(IntermediateOutputPath.Replace('\','/').TrimEnd('/').EndsWith('$(RuntimeIdentifier)')) ">$(IntermediateOutputPath)linked\ - <_SidecarLinkedDir Condition=" '$(_SidecarLinkedDir)' == '' ">$(IntermediateOutputPath)$(RuntimeIdentifier)\linked\ + <_SidecarLinkedDir Condition=" $(IntermediateOutputPath.Replace('\','/').TrimEnd('/').EndsWith('$(RuntimeIdentifier)')) ">$(IntermediateOutputPath)$(_SidecarSubDir) + <_SidecarLinkedDir Condition=" '$(_SidecarLinkedDir)' == '' ">$(IntermediateOutputPath)$(RuntimeIdentifier)\$(_SidecarSubDir) - <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(IntermediateOutputPath)%(RuntimeIdentifier)\linked\%(Filename).jlo.xml')" /> - <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(IntermediateOutputPath)%(RuntimeIdentifier)\linked\%(Filename).typemap.xml')" /> + <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(IntermediateOutputPath)%(RuntimeIdentifier)\$(_SidecarSubDir)%(Filename).jlo.xml')" /> + <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(IntermediateOutputPath)%(RuntimeIdentifier)\$(_SidecarSubDir)%(Filename).typemap.xml')" /> <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(_SidecarLinkedDir)%(Filename).jlo.xml')" /> <_SidecarXmlCopySource Include="@(_NonCompositeAssemblies->'$(_SidecarLinkedDir)%(Filename).typemap.xml')" /> - @@ -3109,7 +3178,7 @@ because xbuild doesn't support framework reference assemblies. From d5d619ee908d0f8231cd5bbcba7cf0912dd6798f Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 2 Apr 2026 18:44:49 +0200 Subject: [PATCH 2/2] Address review: add Inputs/Outputs incrementality, remove duplicate FileWrites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Inputs/Outputs to _LinkAssembliesNoShrink using @(IntermediateAssembly) and $(_AndroidBuildPropertiesCache) as inputs, and a stamp file as output. This prevents SaveChangedAssemblyStep from re-stamping assembly timestamps on every build, which would cascade through downstream targets. - Touch stamp file after successful completion. - Remove duplicate FileWrites entries — the glob $(_LinkAssembliesNoShrinkDir)** already covers all files in the directory. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Xamarin.Android.Common.targets | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 99ce63468c2..c702e5717f7 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1438,7 +1438,9 @@ because xbuild doesn't support framework reference assemblies. --> + Condition=" '$(PublishTrimmed)' != 'true' and '$(_ComputeFilesToPublishForRuntimeIdentifiers)' == 'true' " + Inputs="@(IntermediateAssembly);$(_AndroidBuildPropertiesCache)" + Outputs="$(_AndroidStampDirectory)_LinkAssembliesNoShrink.stamp"> <_LinkAssembliesNoShrinkDir>$(IntermediateOutputPath)android\linked-noshrink\ @@ -1498,13 +1500,12 @@ because xbuild doesn't support framework reference assemblies. - + + - - - +