Skip to content

[CoreCLR] Build R2R images for SDK assemblies in Debug builds #10760

Open

Description

@simonrozsival

Android framework version

net11.0-android (Preview)

Affected platform version

.NET 11

Description

To improve runtime performance in Debug builds, we could pre-compile R2R images for all the libraries (Mono.Android.dll, ideally also Microsoft.Maui.Controls.dll and other MAUI assemblies) which don't change after they are restored.

The idea is to create the R2R image only during the first Debug build for a given target RID and cache this image in the obj/Debug/<rid>/r2r directory. This step should be skipped on any subsequent builds of the app (requires a build test).

The pre-built native images need to be included in the app alongside the managed assemblies so that CoreCLR will load them and avoid JITting code at startup. I wonder if we should embed the images into the .dll directly instead of creating a separate .ni.dll so that we don't need to make any changes to FastDev.

Open questions:

  • Can we build a composite image of all .NET for Android and .NET MAUI assemblies?
  • Does this change require changes to FastDev?
  • Do we need to make changes to AssemblyStoreBuilder (ClrAddIgnoredNativeImageAssembly), or is it only relevant for Release builds?

Reference iOS implementation

Activity

  1. added this to the .NET 11 milestone on Feb 4, 2026
  2. jonathanpeppers commented on Jun 9, 2026

    @jonathanpeppers
    Member

    An alternative to building R2R images on the first Debug build of every app: we could R2R Mono.Android.dll ahead of time at SDK build time and ship the pre-compiled images in the workload itself. This avoids any per-developer / per-app first-build cost.

    Rough sketch of how it would fit into our current pack layout (after #10038 / #9606):

    • SDK build: run crossgen2 over Mono.Android.dll (and likely Java.Interop.dll / Mono.Android.Runtime.dll) once per Android RID (android-arm, android-arm64, android-x86, android-x64) targeting CoreCLR.
    • Managed pack (Microsoft.Android.Runtime.Managed.*.android) — the architecture-less pack that currently contains the single shared Mono.Android.dll — would no longer be consumed by CoreCLR apps. It remains the source of Mono.Android.dll for MonoVM and NativeAOT, which don't benefit from R2R images.
    • CoreCLR runtime packs (Microsoft.Android.Runtime.CoreCLR.<api>.<rid>) — which today only contain per-RID native assets (libnet-android.*.so, libpinvoke-override-*.a, etc.) — would also carry the R2R'd, per-RID copy of Mono.Android.dll (and friends). The SDK targets would resolve Mono.Android.dll from this pack when $(_AndroidRuntime) == CoreCLR, in preference to the managed pack.

    Trade-offs vs. the build-time approach in this issue:

    The two approaches are complementary: ship pre-R2R'd SDK assemblies via the CoreCLR packs, and use the build-time mechanism described above for user code + MAUI. Related: #10792 (pre-generating the Mono.Android trimmable type map) lines up naturally — if the typemap is generated into a Mono.Android.TrimmableTypeMap.dll at SDK build time, we can crossgen2 it in the same step.

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

Metadata

Metadata

Labels

Area: CoreCLRIssues that only occur when using CoreCLR.needs-triageIssues that need to be assigned.

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions