This content was created with assistance from AI.
The _PostTrimmingPipeline target in Microsoft.Android.Sdk.TypeMap.LlvmIr.targets includes all .dll files from @(ResolvedFileToPublish) without filtering out satellite assemblies:
<_PostTrimmingAssembly Include="@(ResolvedFileToPublish)" Condition=" '%(Extension)' == '.dll' " />
After ILLink runs, linked assemblies have their paths updated to the per-RID intermediate output directory, but satellite assemblies (e.g., ar/Microsoft.Maui.Controls.resources.dll) are not processed by ILLink and retain their original paths in the shared NuGet package cache. The PostTrimmingPipeline task opens every assembly with ReadWrite = true via DirectoryAssemblyResolver, which takes an exclusive file lock. When _AndroidBuildRuntimeIdentifiersInParallel is true (the default), multiple inner builds each run _PostTrimmingPipeline and try to exclusively open the same satellite assemblies from the shared cache simultaneously, causing IOException: file being used by another process.
This was observed in dotnet/maui CI on PR dotnet/maui#34552 (build) where SimpleTemplateTest.Build and SimpleTemplateTest.BuildWithMauiVersion integration tests consistently fail on Windows with TrimMode=partial in Release configuration. The failures appeared with the Android SDK version bump from 36.1.99-ci.main.217 to 36.99.0-ci.main.53.
Suggested fix
The .NET SDK already marks ILLink-processed assemblies with PostprocessAssembly=true metadata (set by _ComputeAssembliesToPostprocessOnPublish in Microsoft.NET.Publish.targets). This metadata survives the ILLink Remove/Include cycle because MSBuild item transforms preserve metadata. Satellite assemblies never receive this metadata. The fix is to filter on it:
<_PostTrimmingAssembly Include="@(ResolvedFileToPublish)"
Condition=" '%(Extension)' == '.dll' and '%(PostprocessAssembly)' == 'true' " />
None of the pipeline steps (CheckForObsoletePreserveAttribute, StripEmbeddedLibraries, RemoveResourceDesigner, FixAbstractMethods, AddKeepAlives) need to process satellite assemblies — they operate on types, native embedded resources, and method bodies.
The
_PostTrimmingPipelinetarget inMicrosoft.Android.Sdk.TypeMap.LlvmIr.targetsincludes all.dllfiles from@(ResolvedFileToPublish)without filtering out satellite assemblies:After ILLink runs, linked assemblies have their paths updated to the per-RID intermediate output directory, but satellite assemblies (e.g.,
ar/Microsoft.Maui.Controls.resources.dll) are not processed by ILLink and retain their original paths in the shared NuGet package cache. ThePostTrimmingPipelinetask opens every assembly withReadWrite = trueviaDirectoryAssemblyResolver, which takes an exclusive file lock. When_AndroidBuildRuntimeIdentifiersInParallelis true (the default), multiple inner builds each run_PostTrimmingPipelineand try to exclusively open the same satellite assemblies from the shared cache simultaneously, causingIOException: file being used by another process.This was observed in dotnet/maui CI on PR dotnet/maui#34552 (build) where
SimpleTemplateTest.BuildandSimpleTemplateTest.BuildWithMauiVersionintegration tests consistently fail on Windows withTrimMode=partialin Release configuration. The failures appeared with the Android SDK version bump from36.1.99-ci.main.217to36.99.0-ci.main.53.Suggested fix
The .NET SDK already marks ILLink-processed assemblies with
PostprocessAssembly=truemetadata (set by_ComputeAssembliesToPostprocessOnPublishinMicrosoft.NET.Publish.targets). This metadata survives the ILLink Remove/Include cycle because MSBuild item transforms preserve metadata. Satellite assemblies never receive this metadata. The fix is to filter on it:None of the pipeline steps (
CheckForObsoletePreserveAttribute,StripEmbeddedLibraries,RemoveResourceDesigner,FixAbstractMethods,AddKeepAlives) need to process satellite assemblies — they operate on types, native embedded resources, and method bodies.