From 86ee19caacc4842ef9c6a4600d1528abc6823cea Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 25 May 2026 16:34:48 +0200 Subject: [PATCH 01/10] [tests] Add trimmable DotNetRun cases Add Release and Debug trimmable typemap coverage to the DotNetRun device integration test using CoreCLR. Fixes #11019 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index cb0ab1c00ba..c16ffc492f9 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -56,6 +56,9 @@ static IEnumerable Get_DotNetRun_Data () //AddTestData (false, "managed", runtime); } + AddTestData (true, "trimmable", AndroidRuntime.CoreCLR); + AddTestData (false, "trimmable", AndroidRuntime.CoreCLR); + return ret; void AddTestData (bool isRelease, string typemapImplementation, AndroidRuntime runtime) From 343829998523648859fe5ac07e9a13e7f24f06ef Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Mon, 25 May 2026 16:37:34 +0200 Subject: [PATCH 02/10] [tests] Cover NativeAOT trimmable DotNetRun Add Release NativeAOT coverage for the trimmable typemap DotNetRun device integration test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index c16ffc492f9..c54928c2f41 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -58,6 +58,7 @@ static IEnumerable Get_DotNetRun_Data () AddTestData (true, "trimmable", AndroidRuntime.CoreCLR); AddTestData (false, "trimmable", AndroidRuntime.CoreCLR); + AddTestData (true, "trimmable", AndroidRuntime.NativeAOT); return ret; From 7760f70df84824fe984b9d8884284046bb095bc0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 05:00:21 +0000 Subject: [PATCH 03/10] tests: ignore failing Release CoreCLR trimmable DotNetRun case Agent-Logs-Url: https://github.com/dotnet/android/sessions/9552bfeb-121e-4610-bd28-49396c6295a7 Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index c54928c2f41..72edd60d019 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -93,6 +93,10 @@ public void DotNetRun (bool isRelease, string typemapImplementation, AndroidRunt Assert.Ignore ("NativeAOT doesn't work with LLVM-IR typemaps"); } + if (runtime == AndroidRuntime.CoreCLR && isRelease && typemapImplementation == "trimmable") { + Assert.Ignore ("dotnet run --no-build is currently failing for Release CoreCLR trimmable typemap"); + } + var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease }; From cc33825c1f82c1b0f3a70c4c5a9f00c5478524a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 05:03:41 +0000 Subject: [PATCH 04/10] tests: document temporary ignore for Release CoreCLR trimmable DotNetRun Agent-Logs-Url: https://github.com/dotnet/android/sessions/9552bfeb-121e-4610-bd28-49396c6295a7 Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com> --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 72edd60d019..30c17be58ed 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -94,7 +94,7 @@ public void DotNetRun (bool isRelease, string typemapImplementation, AndroidRunt } if (runtime == AndroidRuntime.CoreCLR && isRelease && typemapImplementation == "trimmable") { - Assert.Ignore ("dotnet run --no-build is currently failing for Release CoreCLR trimmable typemap"); + Assert.Ignore ("TODO: re-enable when dotnet run --no-build succeeds for Release CoreCLR trimmable typemap in MSBuildDeviceIntegration"); } var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { From 5a2712949b8f2d8041a02bb59b49b9431bb0aa16 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 3 Jun 2026 18:14:32 +0200 Subject: [PATCH 05/10] Renormalize banned-apis.targets line endings to LF The dependabot bump (#11562) committed banned-apis.targets with CRLF bytes stored directly in the git blob. Since .gitattributes declares `*.targets eol=crlf`, the blob must be stored normalized (LF) and only converted to CRLF on checkout. The un-normalized blob caused the CI 'Ensure no modified/untracked files' check to fail because git's renormalization detection flagged the file as modified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- build-tools/banned-apis/banned-apis.targets | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/build-tools/banned-apis/banned-apis.targets b/build-tools/banned-apis/banned-apis.targets index b75161c9f1f..2ce94ab256a 100644 --- a/build-tools/banned-apis/banned-apis.targets +++ b/build-tools/banned-apis/banned-apis.targets @@ -1,9 +1,9 @@ - - - RS0030 - - - - - - + + + RS0030 + + + + + + From aab5a5de692ba9f8583c3849a0a04599e2e330ed Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 3 Jun 2026 21:28:32 +0200 Subject: [PATCH 06/10] tests: ignore Debug CoreCLR trimmable DotNetRun (same dotnet run --no-build failure) The Debug CoreCLR trimmable DotNetRun case fails identically to the already-ignored Release case: `dotnet run --no-build` re-runs GenerateNativeApplicationConfigSources, which throws XAGCA7023 because obj/Debug/android/assets//Mono.Android.dll is missing in the no-build incremental state. Broaden the existing ignore to cover both Debug and Release CoreCLR trimmable until the underlying no-build issue is fixed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index cc019017c93..4729684d419 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -93,8 +93,11 @@ public void DotNetRun (bool isRelease, string typemapImplementation, AndroidRunt Assert.Ignore ("NativeAOT doesn't work with LLVM-IR typemaps"); } - if (runtime == AndroidRuntime.CoreCLR && isRelease && typemapImplementation == "trimmable") { - Assert.Ignore ("TODO: re-enable when dotnet run --no-build succeeds for Release CoreCLR trimmable typemap in MSBuildDeviceIntegration"); + // `dotnet run --no-build` re-runs GenerateNativeApplicationConfigSources, which fails with + // XAGCA7023 because obj//android/assets//Mono.Android.dll is not present in the + // no-build incremental state for the CoreCLR trimmable typemap (both Debug and Release). + if (runtime == AndroidRuntime.CoreCLR && typemapImplementation == "trimmable") { + Assert.Ignore ("TODO: re-enable when dotnet run --no-build succeeds for CoreCLR trimmable typemap in MSBuildDeviceIntegration"); } var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { From 6e4bb59dd3423fce081da101fd1c6b95386946c0 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 4 Jun 2026 00:45:38 +0200 Subject: [PATCH 07/10] [TrimmableTypeMap] Fix dotnet run --no-build for trimmable CoreCLR The trimmable _GenerateJavaStubs target listed _CleanIntermediateIfNeeded in its DependsOnTargets. On a full build that is redundant (the target already runs early via _AndroidBuildDependsOn in BuildOrder.targets). But during an incremental deploy that does not rebuild (the Install/DeployToDevice chain used by `dotnet run` without a build), the early Build chain never executes, so this was the only invocation of _CleanIntermediateIfNeeded -- and it ran late, *after* _PrepareAssemblies had already populated obj//android/assets//*.dll. It then deleted obj//android, and because _PrepareAssemblies had already executed it was skipped and did not recreate the assemblies. _GeneratePackageManagerJava then failed with XAGCA7023 (DirectoryNotFoundException on assets//Mono.Android.dll). Remove _CleanIntermediateIfNeeded from the trimmable _GenerateJavaStubs DependsOnTargets so it matches the llvm-ir sibling target, which already omits it. Cleaning still happens early for full builds via BuildOrder.targets. With this fix, the trimmable DotNetRun scenarios (Debug CoreCLR, Release CoreCLR, NativeAOT) build, deploy, and launch on device, so remove the Assert.Ignore guard that skipped the CoreCLR trimmable cases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...Microsoft.Android.Sdk.TypeMap.Trimmable.targets | 14 +++++++++++++- .../Tests/InstallAndRunTests.cs | 7 ------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets index e98c23cf5e6..11e1cdb222e 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets @@ -251,8 +251,20 @@ We keep _GetGenerateJavaStubsInputs in DependsOnTargets so that downstream targets (_GetGeneratePackageManagerJavaInputs) can still read @(_GenerateJavaStubsInputs). --> + diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs index 4729684d419..033dec10628 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs @@ -93,13 +93,6 @@ public void DotNetRun (bool isRelease, string typemapImplementation, AndroidRunt Assert.Ignore ("NativeAOT doesn't work with LLVM-IR typemaps"); } - // `dotnet run --no-build` re-runs GenerateNativeApplicationConfigSources, which fails with - // XAGCA7023 because obj//android/assets//Mono.Android.dll is not present in the - // no-build incremental state for the CoreCLR trimmable typemap (both Debug and Release). - if (runtime == AndroidRuntime.CoreCLR && typemapImplementation == "trimmable") { - Assert.Ignore ("TODO: re-enable when dotnet run --no-build succeeds for CoreCLR trimmable typemap in MSBuildDeviceIntegration"); - } - var proj = new XamarinAndroidApplicationProject (packageName: PackageUtils.MakePackageName (runtime)) { IsRelease = isRelease }; From 1169b3bc3ca3fd26515a73f0b8defd1a73b7145f Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 4 Jun 2026 08:06:35 +0200 Subject: [PATCH 08/10] [TrimmableTypeMap] Retry post-trim Java source cleanup GenerateTrimmableTypeMap cleans the post-trim Java source output directory before copying the Java sources that remain after trimming. On CI this cleanup can fail transiently with Directory not empty while recursively deleting nested source directories, which surfaces as XAGTT7024 and fails otherwise valid CoreCLR trimmable builds. Use the same retry policy and transient error handling as RemoveDirFixed for this internal cleanup path, including access denied, sharing violation, and directory-not-empty retries. The cleanup remains strict: non-transient delete errors still fail the build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Tasks/GenerateTrimmableTypeMap.cs | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs index 9a03ef4ff21..1ac7a870c7a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs @@ -4,7 +4,9 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Runtime.InteropServices; using System.Text; +using System.Threading; using System.Xml.Linq; using Microsoft.Android.Build.Tasks; using Microsoft.Android.Sdk.TrimmableTypeMap; @@ -15,6 +17,10 @@ namespace Xamarin.Android.Tasks; public class GenerateTrimmableTypeMap : AndroidTask { + const int ERROR_ACCESS_DENIED = -2147024891; // 0x80070005 + const int ERROR_SHARING_VIOLATION = -2147024864; // 0x80070020 + const int ERROR_DIR_NOT_EMPTY = -2147024751; // 0x80070091 + static readonly string [] DefaultFrameworkAssemblyNames = [ "Java.Interop", "Mono.Android", @@ -130,7 +136,7 @@ public override bool RunTask () Directory.CreateDirectory (OutputDirectory); if (CleanJavaSourceOutputDirectory && Directory.Exists (JavaSourceOutputDirectory)) { - Directory.Delete (JavaSourceOutputDirectory, recursive: true); + DeleteDirectoryWithRetry (JavaSourceOutputDirectory); } Directory.CreateDirectory (JavaSourceOutputDirectory); @@ -381,6 +387,39 @@ static Version ParseTargetFrameworkVersion (string tfv) throw new ArgumentException ($"Cannot parse TargetFrameworkVersion '{tfv}' as a Version."); } + static void DeleteDirectoryWithRetry (string directory) + { + int retryCount = 0; + int attempts = Files.GetFileWriteRetryAttempts (); + int delay = Files.GetFileWriteRetryDelay (); + + while (retryCount <= attempts) { + try { + if (retryCount == 1) { + Files.SetDirectoryWriteable (directory); + } + Directory.Delete (directory, recursive: true); + return; + } catch (Exception e) { + switch (e) { + case DirectoryNotFoundException: + return; + case UnauthorizedAccessException: + case IOException: + int code = Marshal.GetHRForException (e); + if ((code != ERROR_ACCESS_DENIED && code != ERROR_SHARING_VIOLATION && code != ERROR_DIR_NOT_EMPTY) || retryCount >= attempts) { + throw; + } + break; + default: + throw; + } + } + Thread.Sleep (delay); + retryCount++; + } + } + static string GenerateApplicationRegistrationJava (IReadOnlyList registrationTypes) { var sb = new StringBuilder (); From de245badcabd40aed4c78db4fd053414c6897614 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 4 Jun 2026 09:47:11 +0200 Subject: [PATCH 09/10] [TrimmableTypeMap] Avoid parallel post-trim Java source race CoreCLR trimmable builds with multiple RuntimeIdentifiers run per-RID inner builds in parallel. Those inner builds used the outer intermediate directory for post-trim Java sources so the packaging phase could compile the shared Java output, but every RID inner build generated and cleaned the same obj//typemap/linked-java directory. That made the post-trim Java source generation race with itself. CI observed this as XAGTT7024 / Directory not empty while one inner build deleted the shared linked-java directory as another inner build was also using it. Retrying the recursive delete masks the symptom but leaves the shared-output race. Pass the outer RuntimeIdentifiers list into inner builds and let only the first RID inner build generate the shared post-trim Java sources. The output remains in the outer intermediate directory where _GenerateJavaStubs expects it, while parallel inner builds no longer clean or write the same directory. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...oft.Android.Sdk.AssemblyResolution.targets | 1 + ...roid.Sdk.TypeMap.Trimmable.CoreCLR.targets | 2 +- ...soft.Android.Sdk.TypeMap.Trimmable.targets | 3 ++ .../Tasks/GenerateTrimmableTypeMap.cs | 41 +------------------ 4 files changed, 6 insertions(+), 41 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 efb8c209f7b..224baf6ca37 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 @@ -122,6 +122,7 @@ _ResolveAssemblies MSBuild target. ;_OuterIntermediateSatelliteAssembliesWithTargetPath=@(IntermediateSatelliteAssembliesWithTargetPath) ;_OuterOutputPath=$(OutputPath) ;_OuterIntermediateOutputPath=$(IntermediateOutputPath) + ;_OuterRuntimeIdentifiers=$(RuntimeIdentifiers) ;_OuterCustomViewMapFile=$(_CustomViewMapFile) ;_AndroidNdkDirectory=$(_AndroidNdkDirectory) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets index 293f19585ef..d63890a4b6c 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets @@ -49,7 +49,7 @@ $(_TypeMapBaseOutputDir)typemap/java <_TypeMapAssembliesListFile>$(_TypeMapOutputDirectory)typemap-assemblies.txt <_PostTrimTypeMapJavaOutputDirectory>$(_TypeMapBaseOutputDir)typemap/linked-java + <_PostTrimTypeMapRuntimeIdentifiers Condition=" '$(_OuterRuntimeIdentifiers)' != '' ">$(_OuterRuntimeIdentifiers) + <_PostTrimTypeMapRuntimeIdentifiers Condition=" '$(_PostTrimTypeMapRuntimeIdentifiers)' == '' ">$(RuntimeIdentifiers) + <_PostTrimTypeMapFirstRuntimeIdentifier Condition=" '$(_PostTrimTypeMapRuntimeIdentifiers)' != '' ">$([System.String]::Copy('$(_PostTrimTypeMapRuntimeIdentifiers)').Split(';')[0]) <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' and '$(_AndroidRuntime)' == 'CoreCLR' and '$(PublishTrimmed)' == 'true' ">$(_PostTrimTypeMapJavaOutputDirectory) <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' ">$(_TypeMapJavaOutputDirectory) <_PostTrimTrimmableTypeMapJavaStamp>$(_TypeMapBaseOutputDir)stamp/_GeneratePostTrimTrimmableTypeMapJavaSources.stamp diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs index 1ac7a870c7a..9a03ef4ff21 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs @@ -4,9 +4,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; -using System.Runtime.InteropServices; using System.Text; -using System.Threading; using System.Xml.Linq; using Microsoft.Android.Build.Tasks; using Microsoft.Android.Sdk.TrimmableTypeMap; @@ -17,10 +15,6 @@ namespace Xamarin.Android.Tasks; public class GenerateTrimmableTypeMap : AndroidTask { - const int ERROR_ACCESS_DENIED = -2147024891; // 0x80070005 - const int ERROR_SHARING_VIOLATION = -2147024864; // 0x80070020 - const int ERROR_DIR_NOT_EMPTY = -2147024751; // 0x80070091 - static readonly string [] DefaultFrameworkAssemblyNames = [ "Java.Interop", "Mono.Android", @@ -136,7 +130,7 @@ public override bool RunTask () Directory.CreateDirectory (OutputDirectory); if (CleanJavaSourceOutputDirectory && Directory.Exists (JavaSourceOutputDirectory)) { - DeleteDirectoryWithRetry (JavaSourceOutputDirectory); + Directory.Delete (JavaSourceOutputDirectory, recursive: true); } Directory.CreateDirectory (JavaSourceOutputDirectory); @@ -387,39 +381,6 @@ static Version ParseTargetFrameworkVersion (string tfv) throw new ArgumentException ($"Cannot parse TargetFrameworkVersion '{tfv}' as a Version."); } - static void DeleteDirectoryWithRetry (string directory) - { - int retryCount = 0; - int attempts = Files.GetFileWriteRetryAttempts (); - int delay = Files.GetFileWriteRetryDelay (); - - while (retryCount <= attempts) { - try { - if (retryCount == 1) { - Files.SetDirectoryWriteable (directory); - } - Directory.Delete (directory, recursive: true); - return; - } catch (Exception e) { - switch (e) { - case DirectoryNotFoundException: - return; - case UnauthorizedAccessException: - case IOException: - int code = Marshal.GetHRForException (e); - if ((code != ERROR_ACCESS_DENIED && code != ERROR_SHARING_VIOLATION && code != ERROR_DIR_NOT_EMPTY) || retryCount >= attempts) { - throw; - } - break; - default: - throw; - } - } - Thread.Sleep (delay); - retryCount++; - } - } - static string GenerateApplicationRegistrationJava (IReadOnlyList registrationTypes) { var sb = new StringBuilder (); From e400d73ee8349ebadcbcf5caafa0c9ae974e7816 Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Thu, 4 Jun 2026 10:16:44 +0200 Subject: [PATCH 10/10] [TrimmableTypeMap] Generate post-trim Java sources in outer build The trimmable Java sources are RID-independent, even though the linked assembly inputs are produced by per-RID inner builds. Generating those Java sources from inside the parallel RuntimeIdentifier inner builds made multiple inner builds clean and write the same outer intermediate linked-java directory. Move post-trim Java source generation to the outer build after _ResolveAssemblies has collected the per-RID ResolvedFileToPublish items. The target now runs once, uses a representative RID's linked assemblies as input for the RID-independent Java sources, and leaves the output in the outer intermediate directory where _GenerateJavaStubs expects it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Microsoft.Android.Sdk.AssemblyResolution.targets | 1 - ...icrosoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets | 8 ++++---- .../Microsoft.Android.Sdk.TypeMap.Trimmable.targets | 5 ++--- 3 files changed, 6 insertions(+), 8 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 224baf6ca37..efb8c209f7b 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 @@ -122,7 +122,6 @@ _ResolveAssemblies MSBuild target. ;_OuterIntermediateSatelliteAssembliesWithTargetPath=@(IntermediateSatelliteAssembliesWithTargetPath) ;_OuterOutputPath=$(OutputPath) ;_OuterIntermediateOutputPath=$(IntermediateOutputPath) - ;_OuterRuntimeIdentifiers=$(RuntimeIdentifiers) ;_OuterCustomViewMapFile=$(_CustomViewMapFile) ;_AndroidNdkDirectory=$(_AndroidNdkDirectory) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets index d63890a4b6c..b21afc1b6e4 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets @@ -49,14 +49,14 @@ <_PostTrimTrimmableTypeMapInputAssemblies Include="@(ResolvedFileToPublish)" - Condition=" '%(Extension)' == '.dll' " /> + Condition=" '%(Extension)' == '.dll' and ('%(RuntimeIdentifier)' == '' or '$(_PostTrimTypeMapFirstRuntimeIdentifier)' == '' or '%(RuntimeIdentifier)' == '$(_PostTrimTypeMapFirstRuntimeIdentifier)') " /> $(_TypeMapBaseOutputDir)typemap/java <_TypeMapAssembliesListFile>$(_TypeMapOutputDirectory)typemap-assemblies.txt <_PostTrimTypeMapJavaOutputDirectory>$(_TypeMapBaseOutputDir)typemap/linked-java - <_PostTrimTypeMapRuntimeIdentifiers Condition=" '$(_OuterRuntimeIdentifiers)' != '' ">$(_OuterRuntimeIdentifiers) - <_PostTrimTypeMapRuntimeIdentifiers Condition=" '$(_PostTrimTypeMapRuntimeIdentifiers)' == '' ">$(RuntimeIdentifiers) - <_PostTrimTypeMapFirstRuntimeIdentifier Condition=" '$(_PostTrimTypeMapRuntimeIdentifiers)' != '' ">$([System.String]::Copy('$(_PostTrimTypeMapRuntimeIdentifiers)').Split(';')[0]) + <_PostTrimTypeMapFirstRuntimeIdentifier Condition=" '$(RuntimeIdentifiers)' != '' ">$([System.String]::Copy('$(RuntimeIdentifiers)').Split(';')[0]) + <_PostTrimTypeMapFirstRuntimeIdentifier Condition=" '$(_PostTrimTypeMapFirstRuntimeIdentifier)' == '' ">$(RuntimeIdentifier) <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' and '$(_AndroidRuntime)' == 'CoreCLR' and '$(PublishTrimmed)' == 'true' ">$(_PostTrimTypeMapJavaOutputDirectory) <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' ">$(_TypeMapJavaOutputDirectory) <_PostTrimTrimmableTypeMapJavaStamp>$(_TypeMapBaseOutputDir)stamp/_GeneratePostTrimTrimmableTypeMapJavaSources.stamp