Skip to content

Run AssemblyModifierPipeline before R2R#10891

Draft
sbomer wants to merge 4 commits intomainfrom
dev/svbomer/inner-build-pipeline
Draft

Run AssemblyModifierPipeline before R2R#10891
sbomer wants to merge 4 commits intomainfrom
dev/svbomer/inner-build-pipeline

Conversation

@sbomer
Copy link
Member

@sbomer sbomer commented Mar 5, 2026

Move _AfterILLinkAdditionalSteps from the outer build into the inner (per-RID) build using AfterTargets="ILLink". This ensures AssemblyModifierPipeline runs on trimmed IL assemblies BEFORE CreateReadyToRunImages/IlcCompile compiles them to native code, preventing assembly modifications from overwriting R2R/AOT native code with pure IL.

Add _CopySidecarXmlToAssemblyPaths target to copy .jlo.xml and .typemap.xml sidecar files from linked/ to wherever assemblies end up after R2R/AOT (e.g. R2R/, publish/), so outer-build consumers (_GenerateJavaStubs, GenerateTypeMappings) can find them.

Handles: NativeAOT duplicate assemblies (KeepDuplicates="false"), R2R composite assemblies (empty sidecar files), assemblies not in ManagedAssemblyToLink (Touch AlwaysCreate), single-RID vs multi-RID path differences, and framework vs user assembly classification without NuGetPackageId (filter by known framework assembly names).

Move _AfterILLinkAdditionalSteps from the outer build into the inner
(per-RID) build using AfterTargets="ILLink". This ensures
AssemblyModifierPipeline runs on trimmed IL assemblies BEFORE
CreateReadyToRunImages/IlcCompile compiles them to native code,
preventing assembly modifications from overwriting R2R/AOT native
code with pure IL.

Add _CopySidecarXmlToAssemblyPaths target to copy .jlo.xml and
.typemap.xml sidecar files from linked/ to wherever assemblies end
up after R2R/AOT (e.g. R2R/, publish/), so outer-build consumers
(_GenerateJavaStubs, GenerateTypeMappings) can find them.

Handles: NativeAOT duplicate assemblies (KeepDuplicates="false"),
R2R composite assemblies (empty sidecar files), assemblies not in
ManagedAssemblyToLink (Touch AlwaysCreate), single-RID vs multi-RID
path differences, and framework vs user assembly classification
without NuGetPackageId (filter by known framework assembly names).
sbomer added 2 commits March 5, 2026 15:41
In NativeAOT builds, the project's own assembly is not in
@(ManagedAssemblyToLink) — ILLink passes it as a TrimmerRootAssembly.
This caused AssemblyModifierPipeline to skip it, producing no JCW for
MainActivity and failing with XA0103.

Add the root assembly explicitly to _AfterILLinkAssemblies using
Exclude (not KeepDuplicates) to avoid duplicates. KeepDuplicates
compares items including metadata, so a bare Include would be
considered distinct from an existing item with rich metadata from
@(ManagedAssemblyToLink), causing GetPerArchAssemblies() to throw
a duplicate key error in CoreCLR builds. Exclude compares by ItemSpec
only, correctly deduplicating in both scenarios.

Also set HasMonoAndroidReference=true on the root assembly so
IsAndroidAssembly() returns true and FindJavaObjectsStep scans it.
KeepDuplicates="false" compares items INCLUDING metadata, so when
NativeAOT builds produce duplicate @(ManagedAssemblyToLink) entries
for the same assembly (e.g. Java.Interop.dll) with different metadata,
the transformed items survive deduplication and cause
GetPerArchAssemblies() to throw "duplicate key" errors.

Replace KeepDuplicates with the RemoveDuplicates task, which
deduplicates by ItemSpec only, ignoring metadata differences.
@sbomer sbomer self-assigned this Mar 6, 2026
… late

When RuntimeIdentifier is set after path evaluation (e.g. via
MockPrimaryCpuAbi.targets), IntermediateOutputPath does not contain the
RID. The target now detects this and appends the RID explicitly to find
sidecar XML files in the correct linked/ directory.
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.

1 participant