Skip to content

Avoid passing satellite assemblies to post-trimming pipeline #11085

@sbomer

Description

@sbomer

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.

Metadata

Metadata

Assignees

Labels

needs-triageIssues that need to be assigned.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions