Skip to content

[TrimmableTypeMap] _RemoveRegisterAttribute fails on trimmed framework assembly (CheckAaptError... NativeAOT) #11776

Description

@simonrozsival

Summary

CheckAaptErrorNotRaisedForInvalidFileNameWithValidLogicalName(NativeAOT) fails during _RemoveRegisterAttribute (it is not an aapt error despite the test name):

Xamarin.Android.Common.targets(2014,3): error XACIC7028: System.IO.FileNotFoundException:
  Could not find file '.../microsoft.netcore.app.runtime.nativeaot.android-arm64/11.0.0-preview.6.26322.111/runtimes/android-arm64/lib/net11.0/shrunk/System.Net.HttpListener.dll'.
   at Microsoft.Android.Build.Tasks.Files.CopyIfChanged(String source, String destination)
   at Xamarin.Android.Tasks.CopyIfChanged.RunTask()

Diagnosis

_RemoveRegisterAttribute (Common.targets ~2011, runs in Release / AndroidLinkMode != None) does:

<CopyIfChanged SourceFiles="@(_ResolvedAssemblies)" DestinationFiles="@(_ShrunkAssemblies)" />

For the trimmable NativeAOT path, @(_ResolvedAssemblies) contains System.Net.HttpListener.dll pointing at a .../shrunk/ path that does not exist — the framework assembly was trimmed away by ILC, but the _ResolvedAssemblies/_ShrunkAssemblies lists (computed before/around ILC) still reference it at its expected post-shrink location. CopyIfChanged then throws on the missing source.

The LlvmIr/legacy path overrides _RemoveRegisterAttribute (Microsoft.Android.Sdk.TypeMap.LlvmIr.targets ~372). The trimmable path uses the Common default and only patches in the generated TypeMap DLLs (_PrepareTrimmableTypeMapAssemblies, Trimmable.targets ~248-275) to keep source/destination counts in sync — but does not account for framework assemblies that ILC removes.

This only reproduces when the app references framework assemblies that get trimmed (e.g. System.Net.HttpListener via the default project); a minimal app that doesn't pull them in builds fine. The test became a failure once the trimmable NativeAOT build flow advanced far enough to reach _RemoveRegisterAttribute (it was not observed in earlier, more-broken builds).

Fix direction (needs design)

  • Filter @(_ResolvedAssemblies) / @(_ShrunkAssemblies) for the trimmable NativeAOT path to only assemblies that survive ILC (exist on disk), keeping source/destination aligned; or
  • Make _RemoveRegisterAttribute tolerate missing sources; or
  • Override _RemoveRegisterAttribute for the trimmable NativeAOT path (as LlvmIr does) so it doesn't depend on the illink "shrunk" assembly layout.

Acceptance criteria

  • CheckAaptErrorNotRaisedForInvalidFileNameWithValidLogicalName(NativeAOT) passes.
  • Apps referencing trimmed framework assemblies (System.Net.HttpListener, etc.) build under NativeAOT.
  • Assembly store / _RemoveRegisterAttribute counts remain consistent.

References

  • Repro test: CheckAaptErrorNotRaisedForInvalidFileNameWithValidLogicalName (src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs).
  • Code: Xamarin.Android.Common.targets (_RemoveRegisterAttribute ~2011), Microsoft.Android.Sdk.TypeMap.Trimmable.targets (_PrepareTrimmableTypeMapAssemblies ~248), Microsoft.Android.Sdk.TypeMap.LlvmIr.targets (_RemoveRegisterAttribute override ~372).

Metadata

Metadata

Assignees

No one assigned

    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