Skip to content

[TrimmableTypeMap] Preserve trimmable typemap outputs on no-op builds#11472

Merged
jonathanpeppers merged 4 commits into
mainfrom
dev/simonrozsival/trimmable-typemap-incremental-clean
May 27, 2026
Merged

[TrimmableTypeMap] Preserve trimmable typemap outputs on no-op builds#11472
jonathanpeppers merged 4 commits into
mainfrom
dev/simonrozsival/trimmable-typemap-incremental-clean

Conversation

@simonrozsival
Copy link
Copy Markdown
Member

@simonrozsival simonrozsival commented May 24, 2026

Summary

  • Add a new _RecordTrimmableTypeMapFileWrites target that re-emits the trimmable typemap's dynamic outputs (generated typemap DLLs, Java sources, copied android/src/** files, acw-map.txt, AndroidManifest.xml, ApplicationRegistration.java, and the typemap assemblies list) into @(FileWrites) on no-op builds.
  • Hook the new target into the public $(IncrementalCleanDependsOn) extension point so MSBuild''s IncrementalClean sees the prior outputs and does not treat them as orphaned when _GenerateJavaStubs / _GenerateTrimmableTypeMap are skipped.
  • Refactor the _GeneratedTypeMapAssembliesFromList fan-out in _AddTrimmableTypeMapAssembliesToResolvedAssemblies to populate a single _TrimmableTypeMapResolvedAssemblies item group and include it in both _ResolvedAssemblies and _ShrunkAssemblies, keeping metadata in sync.
  • Extend Build_WithTrimmableTypeMap_IncrementalBuild to assert that at least one typemap DLL is produced on the first build and that every generated typemap DLL still exists after the no-op second build.

Related to #10958.

Relevant sub-issues:

Validation

  • ./dotnet-local.sh build src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Xamarin.Android.Build.Tests.csproj -p:Configuration=Debug -v:minimal
  • ANDROID_SERIAL=emulator-5554 ./dotnet-local.sh test bin/TestDebug/net10.0/Xamarin.Android.Build.Tests.dll --filter "Name=Build_WithTrimmableTypeMap_IncrementalBuild" --logger "console;verbosity=detailed" (test run succeeded; selected cases skipped/inconclusive locally because commercial build targets are unavailable; False,NativeAOT is an unsupported configuration)

Generated trimmable typemap outputs are dynamic, so no-op builds can skip the targets that normally add them to FileWrites. Replay the prior generated outputs before IncrementalClean so they are not treated as orphaned and removed before packaging evaluates its inputs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival changed the title Preserve trimmable typemap outputs on no-op builds [TrimmableTypeMap] Preserve trimmable typemap outputs on no-op builds May 24, 2026
@simonrozsival simonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 24, 2026
@simonrozsival simonrozsival marked this pull request as ready for review May 25, 2026 08:32
Copilot AI review requested due to automatic review settings May 25, 2026 08:32
@simonrozsival simonrozsival added the ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). label May 25, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a trimmable typemap incremental-build issue where MSBuild’s IncrementalClean could delete previously generated typemap DLLs / Java outputs on no-op builds (because skipped targets don’t re-populate @(FileWrites)). It replays the prior dynamic outputs into @(FileWrites) early in the build and strengthens the incremental test to ensure the generated typemap assemblies survive a no-op rebuild.

Changes:

  • Add a _RecordTrimmableTypeMapFileWrites target that re-emits typemap-generated DLL/Java outputs into @(FileWrites) before _CleanGetCurrentAndPriorFileWrites runs.
  • Refactor typemap assembly item construction via a dedicated @(_TrimmableTypeMapResolvedAssemblies) item list and then feed it into both @(_ResolvedAssemblies) and @(_ShrunkAssemblies).
  • Extend Build_WithTrimmableTypeMap_IncrementalBuild to assert typemap DLLs from the first build still exist after a no-op second build.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs Adds an assertion that typemap DLL outputs persist across a no-op rebuild where _GenerateJavaStubs is skipped.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets Replays prior dynamic typemap outputs into @(FileWrites) before IncrementalClean and slightly restructures typemap DLL item population for packaging/native config.

simonrozsival and others added 2 commits May 27, 2026 08:13
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
Copy link
Copy Markdown
Member Author

/review

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 27, 2026

Android PR Reviewer completed successfully!

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — Clean, well-designed incremental build fix

Summary: This PR correctly solves the problem of IncrementalClean deleting dynamically-generated typemap outputs on no-op builds by replaying them into @(FileWrites) via the public $(IncrementalCleanDependsOn) hook. The approach is sound and follows MSBuild best practices.

What's good:

  • The _RecordTrimmableTypeMapFileWrites target is well-placed via IncrementalCleanDependsOn — the right hook for this problem
  • Excellent comment block explaining why the target exists
  • The _TrimmableTypeMapResolvedAssemblies refactoring eliminates metadata duplication cleanly
  • Test coverage directly validates the fix scenario

Minor suggestions posted inline (2 💡):

  1. Redundant stamp file FileWrites entry (already handled by _AddFilesToFileWrites glob)
  2. Missing Assert.IsNotEmpty guard on typemapDlls in the test

⚠️ CI: Could not check CI status (gh is not authenticated in this environment). Please verify CI is green before merging.

Generated by Android PR Reviewer for issue #11472 · ● 13.2M

@simonrozsival
Copy link
Copy Markdown
Member Author

@copilot address review comments

  • _AddFilesToFileWrites (in Xamarin.Android.Common.targets:2663) already adds $(_AndroidStampDirectory)*.stamp via a glob, so this line is a no-op. Removing it would reduce noise and avoid confusion about whether stamps need explicit registration.
  • f Directory.GetFiles returns an empty array (e.g., due to a test infrastructure issue or path change), the foreach loop below silently passes without verifying anything. Adding Assert.IsNotEmpty (typemapDlls) here would catch that case and make the test more robust.

… Assert.IsNotEmpty guard

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 27, 2026

@copilot address review comments

  • _AddFilesToFileWrites (in Xamarin.Android.Common.targets:2663) already adds $(_AndroidStampDirectory)*.stamp via a glob, so this line is a no-op. Removing it would ...

Done in 01cf0d5:

  • Removed the $(_AndroidStampDirectory)_GenerateJavaStubs.stamp line from _RecordTrimmableTypeMapFileWrites — it's already covered by the *.stamp glob in _AddFilesToFileWrites.
  • Added Assert.IsNotEmpty(typemapDlls, ...) immediately after Directory.GetFiles to catch the empty-array case before the foreach.

@jonathanpeppers jonathanpeppers merged commit 0b0290b into main May 27, 2026
3 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/simonrozsival/trimmable-typemap-incremental-clean branch May 27, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot `copilot-cli` or other AIs were used to author this ready-to-review This PR is ready to review/merge, I think any CI failures are just flaky (ignorable). trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants