Skip to content

[Xamarin.Android.Build.Tasks] Stop legacy assembly scans - #12968

Closed
simonrozsival wants to merge 1 commit into
mainfrom
simonrozsival-debug-trimmable-scanning
Closed

simonrozsival wants to merge 1 commit into
mainfrom
simonrozsival-debug-trimmable-scanning

Conversation

@simonrozsival

Copy link
Copy Markdown
Member

Why

Untrimmed builds still enter the _LinkAssembliesNoShrink target when $(PublishTrimmed) is not true. <LinkAssembliesNoShrink/> must stage assemblies and preserve opted-in compatibility fixes, but its shared Xamarin.Android.Tasks.AssemblyModifierPipeline.BuildPipeline() also unconditionally registered FindJavaObjectsStep and FindTypeMapObjectsStep.

That runs the legacy Cecil JCW/type-map scanners alongside the modern trimmable pipeline. The interaction between #12887 (trimmable by default) and #12931 (expanded export coverage) exposes the regression: TrimmableExportReferencePeer.MakeList() exports System.Collections.IList, which the modern generator supports but the legacy importer does not. Building Mono.Android.NET-Tests in untrimmed Debug fails with XALNS7003 and the misleading legacy ArgumentNullException naming connector, before any device tests run.

Change

Remove both legacy scanner registrations outright. Trimmable is the only supported product backend, so there is no LLVM selector, legacy default, fallback, or new task input. Direct callers of <AssemblyModifierPipeline/> now get the assembly-save step only; they no longer perform Java peer scanning.

Keep SaveChangedAssemblyStep and the existing <LinkAssembliesNoShrink/> compatibility/resource-designer/keep-alive steps and ordering unchanged. Leave the modern generator timing and trimmed CoreCLR post-link pipeline unchanged. Modern type maps reference their owners symbolically by assembly/type/member identity, not by the owner's original MVID or metadata tokens.

Add focused coverage proving:

  • Neither legacy scanner is registered, including direct shared-task callers.
  • Opted-in fixes still precede assembly saving.
  • A two-RID untrimmed Debug app can consume a library with the same trimmable-only IList export shape as the real fixture, and produces modern type-map and Java outputs without either legacy XML sidecar.
  • Generated callback references resolve against the actual final staged DLL, including a keep-alive rewrite that changes its MVID.
  • No-op builds preserve output timestamps; body-only changes preserve type-map emission; export-name changes regenerate the modern outputs.

This is a standalone regression fix against main. The original export fixtures remain unmodified. There are no native, LLVM-removal, assembly-store/ELF, R8, localization, or bootstrap changes, and no prerequisite PR.

Validation

Built an independent SDK from main at 976e5528dac9a9a4a18c21cc74b431160ae1d74f using the pinned .NET SDK 12.0.100-alpha.1.26477.101, make prepare, and make leeroy (including extra API bindings and local workload setup). No source/framework/runtime pin overrides were used.

The original unmodified Debug fixture first reproduced the exact XALNS7003 failure against the main-built task binaries. With the final scanner-removal implementation:

Coverage Result
Focused task/build/compatibility/incremental/default-and-rejected-backend tests 32 passed, 0 failed, 0 skipped
Modern generator, incremental, manifest-alias, and RID-callback suites 26 passed, 0 failed, 0 skipped
Mono.Android.NET-Tests, Debug, PublishTrimmed=false, android-arm64 Build succeeds
Same original fixture, Debug JniReferenceLeaks flavor Build succeeds
Same original fixture, Debug, PublishTrimmed=true Build succeeds
Same original fixture, Release Build succeeds

All four original-fixture builds use the same single android-arm64 RID and retain the export tests. Validation is host-side/build-only: no install target, physical device, or emulator was used. Local reruns disable build-server/node reuse after replacing task assemblies to avoid testing a previously loaded DLL; that is only a validation prerequisite, not a product workaround.

Untrimmed builds call <LinkAssembliesNoShrink/>.  The shared
Xamarin.Android.Tasks.AssemblyModifierPipeline registers legacy JCW
and typemap scanners even though trimmable is the only supported
backend.  The IList export coverage added in #12931 exposes this path
after #12887 made trimmable the default, causing XALNS7003 in Debug.

Remove both scanner registrations instead of retaining an LLVM selector
or fallback.  Preserve compatibility fixups, keep-alives and assembly
saving, and leave modern generator timing unchanged.

Add task and app/library regression coverage for legacy-scan absence,
trimmable-only exports, final staged assembly identity and MVID
resolution, and unchanged/body/export-changed incremental builds.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 1, 2026 07:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

An existing regression test still requires the removed .jlo.xml output and will fail.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Removes legacy Cecil scanner registration from assembly modification pipelines while preserving assembly saving and compatibility fixups.

Changes:

  • Removes legacy Java-object and type-map scanners.
  • Adds pipeline-ordering and untrimmed trimmable-build coverage.
  • Verifies modern output generation and incrementality.
File Description
AssemblyModifierPipeline.cs Retains only assembly saving.
LinkerTests.cs Tests scanner removal and step ordering.
TrimmableTypeMapBuildTests.cs Adds end-to-end regression coverage.

pipeline.Steps.Add (findJavaObjectsStep);

// SaveChangedAssemblyStep
// Java peer scanning belongs to the trimmable typemap generator.
@simonrozsival

Copy link
Copy Markdown
Member Author

superseded by #12976

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants