Skip to content

[TrimmableTypeMap] Improve trimmable typemap framework roots#11498

Open
simonrozsival wants to merge 8 commits into
mainfrom
dev/simonrozsival/trimmable-framework-roots
Open

[TrimmableTypeMap] Improve trimmable typemap framework roots#11498
simonrozsival wants to merge 8 commits into
mainfrom
dev/simonrozsival/trimmable-framework-roots

Conversation

@simonrozsival
Copy link
Copy Markdown
Member

@simonrozsival simonrozsival commented May 26, 2026

Splits the trimming improvements out of #11346.

This keeps the product-side trimmable typemap improvements separate from the APK comparison test PR:

  • pass per-assembly typemap entries to ILLink
  • mark framework assembly peers so framework ACW roots can be trimmed correctly
  • support DynamicCodeSupport=false with trimmable typemaps

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 improves the trimmable typemap pipeline so framework-generated peers can be treated as trimmable by default, and updates the CoreCLR trimming/R8 integration to pass the correct typemap entry assemblies to ILLink. It also adds coverage for DynamicCodeSupport=false behavior in trimmable typemap builds.

Changes:

  • Add framework-ACW trimming behavior and tests verifying conditional vs unconditional framework ACW entries.
  • Pass per-assembly *.TypeMap.dll assemblies to ILLink via --typemap-entry-assembly and mark typemap inputs as trimmable.
  • Treat DynamicCodeSupport=false as “dynamic code unavailable” for array typemap sentinel emission, with a new end-to-end build test.

Reviewed changes

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

Show a summary per file
File Description
tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TypeMapModelBuilderTests.cs Adds unit tests validating conditional/unconditional behavior for framework ACW peers.
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs Adds an integration test ensuring DynamicCodeSupport=false is honored and array-rank sentinels are emitted.
src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs Adds configurable framework assembly name inputs and defaults used during typemap generation.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets Updates default max array-rank behavior when dynamic code is disabled and wires framework assembly names into the task.
src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets Passes per-assembly typemap entry assemblies to ILLink, marks typemap DLLs trimmable, and generates proguard configuration post-link.
src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs Marks framework peers (post-scan) to support trimming of framework ACWs.
src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.cs Updates framework peer documentation and allows IsFrameworkAssembly to be mutated post-scan.
Comments suppressed due to low confidence (1)

src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.cs:56

  • IsFrameworkAssembly is now settable on a record type, but other fields (e.g., GenerateArrayEntries) are computed from it during scanning. Allowing IsFrameworkAssembly to change after creation can leave the record in an inconsistent state unless related fields are updated together; prefer keeping it init-only and setting it during scanning (or recomputing dependent fields when changing it).
	/// <summary>
	/// True when the type belongs to a framework assembly supplied by the Android SDK.
	/// Framework ACWs are generated by the SDK and can be trimmed like bindings unless
	/// another rule explicitly roots them.
	/// </summary>
	public bool IsFrameworkAssembly { get; set; }

	/// <summary>
	/// True when per-rank array typemap entries should be generated for this peer.
	/// </summary>
	public bool GenerateArrayEntries { get; set; } = true;

Comment thread src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs Outdated
@simonrozsival simonrozsival changed the title Improve trimmable typemap framework roots [TrimmableTypeMap] Improve trimmable typemap framework roots May 26, 2026
@simonrozsival
Copy link
Copy Markdown
Member Author

@copilot address the review

Copy link
Copy Markdown
Contributor

Copilot AI commented May 26, 2026

@copilot address the review

Addressed in 84c8fcb.

I removed the redundant MarkFrameworkAssemblyPeers() pass in TrimmableTypeMapGenerator (scanner already sets IsFrameworkAssembly), and updated the DynamicCodeSupport test to parse runtimeconfig.json and assert runtimeOptions.configProperties["System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported"] == false instead of using a formatting-dependent string match.

@simonrozsival

This comment was marked as low quality.

simonrozsival and others added 8 commits May 27, 2026 21:01
Add a Release CoreCLR HelloWorld comparison test that builds llvm-ir and trimmable typemap APKs, prints managed and dex diagnostics, and asserts the trimmable typemap does not retain extra typemap-eligible managed or Java entries.

Pass all generated typemap assemblies to ILLink as typemap entry assemblies and mark them trimmable so conditional typemap entries are honored.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generate proguard keep rules for the CoreCLR trimmable typemap path from the linked assemblies, matching the llvm-ir path, and make the APK comparison test use R8 so dex contents are actually shrunk.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Limit --typemap-entry-assembly arguments to generated per-assembly *.TypeMap.dll assemblies that contain TypeMapAttribute entries, instead of treating the root typemap loader assembly as an entry assembly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep SDK framework ACWs conditional unless they are explicitly rooted, and pass framework assembly names through trimmable typemap generation. This allows Mono.Android implementor entries to be trimmed while preserving app ACWs and scanner-rooted components.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Emit array typemap sentinels when dynamic code support is explicitly disabled so CoreCLR trimmable typemap builds can use the no-dynamic-code array path. Keep DynamicCodeSupport enabled by default and cover the explicit opt-out path in tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the APK comparison test scaffolding from this split branch while keeping the DynamicCodeSupport coverage for trimmable typemaps.
Agent-Logs-Url: https://github.com/dotnet/android/sessions/9991cddf-ded2-4c77-8804-19e7a4ecab36

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Pass the root typemap assembly itself to ILLink and configure TypeMapping to load entries from the generated root assembly before runtime typemap initialization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival force-pushed the dev/simonrozsival/trimmable-framework-roots branch from ac57cc4 to 2c25481 Compare May 27, 2026 20:56
@simonrozsival simonrozsival added copilot `copilot-cli` or other AIs were used to author this trimmable-type-map labels May 27, 2026
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 trimmable-type-map

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants