[TrimmableTypeMap] Don't stage shrunk assemblies into the shared runtime pack on NativeAOT#11780
Open
simonrozsival wants to merge 1 commit into
Open
Conversation
…ime pack on NativeAOT CheckCodeBehindIsGenerated(NativeAOT) and CheckOldResourceDesignerWithWrongCasingIsRemoved(True,NativeAOT) failed intermittently in CI with: error XACIC7028: System.IO.FileNotFoundException: Could not find file '.../microsoft.netcore.app.runtime.nativeaot.android-arm64/.../lib/net11.0/shrunk/System.Xml.ReaderWriter.dll' at _RemoveRegisterAttribute (Xamarin.Android.Common.targets). The base _RemoveRegisterAttribute copies every @(_ResolvedAssemblies) into its @(_ShrunkAssemblies) location. For PublishTrimmed builds the framework/ user shrunk destinations live *inside the shared NuGet runtime pack* (.../runtimes/<rid>/lib/net11.0/shrunk/). Because multiple test projects and the parallel per-RID inner builds all target those same shared files, they race and fail intermittently with FileNotFoundException on a clean pack cache. Locally the failure is masked by shrunk/ files left over from previous builds. On NativeAOT these managed framework/user assemblies are compiled to a native shared library by ILC and are never packaged, so the shrunk copies are only ever used as incremental-build inputs (CollectAssemblyFilesToCompress, the one task that reads their content, is already gated to non-NativeAOT). Override _RemoveRegisterAttribute in the trimmable typemap path to redirect the shrunk copies to a project-local intermediate directory instead of the shared pack. They are still produced with CopyIfChanged so the copies keep stable timestamps (preserving the @(_ShrunkAssemblies)/@(_ShrunkFrameworkAssemblies) incremental up-to-date checks), but nothing is ever written into the shared runtime pack. CoreCLR keeps the base behavior since it still packages the managed assemblies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR prevents PublishTrimmed NativeAOT builds in the trimmable typemap path from copying “shrunk” assemblies into the shared runtime pack (NuGet cache), which can cause cross-project/per-RID parallel build races and intermittent XACIC7028 failures. It does so by overriding _RemoveRegisterAttribute to redirect the “shrunk” copy destinations into a project-local intermediate directory for NativeAOT, while keeping the existing behavior for CoreCLR/trimmable runtimes that still package managed assemblies.
Changes:
- Add an override of
_RemoveRegisterAttributein the trimmable typemap targets. - For
'$(_AndroidRuntime)' == 'NativeAOT', rewrite@(_ShrunkAssemblies)/@(_ShrunkFrameworkAssemblies)/@(_ShrunkUserAssemblies)to point under$(MonoAndroidIntermediateAssemblyDir)shrunk\...instead of the shared runtime pack. - Preserve the existing copy behavior (
CopyIfChanged) for non-NativeAOT trimmable runtimes.
Show a summary per file
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets | Overrides _RemoveRegisterAttribute to redirect shrunk assembly staging to a project-local intermediate path for NativeAOT, avoiding writes into shared runtime packs. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
For
PublishTrimmedAndroid builds,_RemoveRegisterAttribute(inXamarin.Android.Common.targets) copies every@(_ResolvedAssemblies)into its@(_ShrunkAssemblies)location. For the framework/user assemblies those shrunk destinations live inside the shared NuGet runtime pack, e.g.:Because multiple test projects — and the parallel per-RID inner builds — all target those same shared files, they race and fail intermittently on a clean pack cache with:
This surfaced as intermittent CI failures in
CheckCodeBehindIsGenerated(NativeAOT)andCheckOldResourceDesignerWithWrongCasingIsRemoved(True,NativeAOT). It does not reproduce locally becauseshrunk/files left over from previous builds mask the missing source.Fixes #11776.
Fix
On NativeAOT the managed framework/user assemblies are compiled to a native shared library by ILC and are never packaged, so these shrunk copies are only ever used as incremental-build inputs —
CollectAssemblyFilesToCompress(the only task that reads their content) is already gated to'$(_AndroidRuntime)' != 'NativeAOT'.This PR overrides
_RemoveRegisterAttributein the trimmable typemap path to, for NativeAOT, redirect the shrunk copies to a project-local intermediate directory ($(MonoAndroidIntermediateAssemblyDir)shrunk\) instead of the shared runtime pack. They are still produced withCopyIfChanged, so the copies keep stable timestamps (only rewritten when content actually changes), which preserves the@(_ShrunkAssemblies)/@(_ShrunkFrameworkAssemblies)incremental up-to-date checks — while nothing is ever written into the shared pack.CoreCLR (and any other trimmable runtime) keeps the base behavior because it still packages the managed assemblies and therefore needs the shrunk copies in place.
Risk
Low and well-scoped:
'$(_AndroidRuntime)' == 'NativeAOT'branch changes behavior; CoreCLR-trimmable replicates the base target exactly.Testing
Verified locally (both runtimes) that
CheckCodeBehindIsGenerated,CheckOldResourceDesignerWithWrongCasingIsRemoved, andCSProjUserFileChanges(incremental) pass, and that the runtime pack'sshrunk/directory is no longer written for NativeAOT builds. Validated on CI in the context of the larger trimmable-typemap work (the two failing tests turned green and stayed green).Sliced out of #11617 for focused review.