From 01308ec7139183e88287f54283082a454b355c81 Mon Sep 17 00:00:00 2001
From: Milos Kotlar <223556219+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 16:07:21 +0200
Subject: [PATCH 1/4] [net11.0] R2R-compile only System.Private.CoreLib for
Debug CoreCLR mobile builds
In Debug builds with CoreCLR on iOS, narrow _NonUserAssemblies to System.Private.CoreLib so that crossgen2 only ReadyToRun-compiles CoreLib and every other framework, MAUI, and NuGet assembly is excluded from R2R via the existing PublishReadyToRunExclude path. Non-R2R'd methods fall back to the CoreCLR interpreter at runtime (JIT is forbidden on iOS), which is the desired inner-loop behavior. Measured on SampleMAUI publish for ios-arm64 Debug: framework dylib drops from 318 MB to 28 MB and the .app bundle shrinks from 395 MB to 132 MB, with a corresponding reduction in crossgen2 time during build. Startup is unchanged in practice because the hot path through CoreLib is still R2R'd; only first-call cost for non-CoreLib methods shifts onto the interpreter, which is negligible for the inner-loop scenarios this default targets. Release builds are unaffected (FilterReadyToRunAssemblies already gates _SelectR2RAssemblies off for Release).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/targets/Microsoft.Sdk.R2R.targets | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dotnet/targets/Microsoft.Sdk.R2R.targets b/dotnet/targets/Microsoft.Sdk.R2R.targets
index 5db954f9fd45..bc35624ded12 100644
--- a/dotnet/targets/Microsoft.Sdk.R2R.targets
+++ b/dotnet/targets/Microsoft.Sdk.R2R.targets
@@ -125,7 +125,7 @@
<_ResolvedAssembliesToPublish Include="@(ResolvedFileToPublish)" Condition="'%(Extension)' == '.dll' And '%(ResolvedFileToPublish.Culture)' == '' And '%(ResolvedFileToPublish.DestinationSubDirectory)' == ''" />
<_NonUserAssemblies
Include="@(_ResolvedAssembliesToPublish)"
- Condition="'%(_ResolvedAssembliesToPublish.NuGetPackageId)' != ''" />
+ Condition="'%(_ResolvedAssembliesToPublish.NuGetPackageId)' != '' And '%(Filename)' == 'System.Private.CoreLib'" />
<_UserAssemblies Include="@(_ResolvedAssembliesToPublish)" Exclude="@(_NonUserAssemblies)" />
From f3d55adef95011b5c2d56790aa9fa2440cdfd34e Mon Sep 17 00:00:00 2001
From: Milos Kotlar <223556219+Copilot@users.noreply.github.com>
Date: Fri, 29 May 2026 16:19:20 +0200
Subject: [PATCH 2/4] Update _SelectR2RAssemblies comment to reflect new filter
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/targets/Microsoft.Sdk.R2R.targets | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dotnet/targets/Microsoft.Sdk.R2R.targets b/dotnet/targets/Microsoft.Sdk.R2R.targets
index bc35624ded12..0ea9c5ed1fca 100644
--- a/dotnet/targets/Microsoft.Sdk.R2R.targets
+++ b/dotnet/targets/Microsoft.Sdk.R2R.targets
@@ -115,8 +115,8 @@
Date: Wed, 3 Jun 2026 16:04:01 +0200
Subject: [PATCH 3/4] [net11.0] Pass excluded framework assemblies as
references to the CoreLib-only R2R composite
Restricting the R2R composite to only System.Private.CoreLib makes the SDK
flag every other framework assembly as hidden from the composite and drop it
from the crossgen2 -r list. The composite is then built with zero references,
producing a native image CoreCLR rejects at startup (FailFast in
NativeImage::Open). Add a target that re-injects the excluded assemblies into
_ReadyToRunCompositeBuildReferences (excluding the composite inputs), so
crossgen2 receives them via -r while they still run as plain IL. Gated to
filtered composite builds, so non-filtered builds are unaffected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/targets/Microsoft.Sdk.R2R.targets | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/dotnet/targets/Microsoft.Sdk.R2R.targets b/dotnet/targets/Microsoft.Sdk.R2R.targets
index 0ea9c5ed1fca..22e92a83d883 100644
--- a/dotnet/targets/Microsoft.Sdk.R2R.targets
+++ b/dotnet/targets/Microsoft.Sdk.R2R.targets
@@ -152,6 +152,17 @@
+
+
+ <_ReadyToRunCompositeBuildReferences
+ Include="@(_ReadyToRunAssembliesToReference)"
+ Exclude="@(_ReadyToRunCompositeBuildInput);@(_ReadyToRunCompositeUnrootedBuildInput)" />
+
+
+
Date: Thu, 4 Jun 2026 12:04:31 +0200
Subject: [PATCH 4/4] Use PublishReadyToRunCompositeRoots for BCL assemblies
---
dotnet/targets/Microsoft.Sdk.R2R.targets | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/dotnet/targets/Microsoft.Sdk.R2R.targets b/dotnet/targets/Microsoft.Sdk.R2R.targets
index 22e92a83d883..3e6b49ad294f 100644
--- a/dotnet/targets/Microsoft.Sdk.R2R.targets
+++ b/dotnet/targets/Microsoft.Sdk.R2R.targets
@@ -115,8 +115,8 @@
<_NonUserAssemblies
Include="@(_ResolvedAssembliesToPublish)"
- Condition="'%(_ResolvedAssembliesToPublish.NuGetPackageId)' != '' And '%(Filename)' == 'System.Private.CoreLib'" />
+ Condition="'%(_ResolvedAssembliesToPublish.NuGetPackageId)' != ''" />
<_UserAssemblies Include="@(_ResolvedAssembliesToPublish)" Exclude="@(_NonUserAssemblies)" />
+
@@ -152,14 +153,11 @@
-
+
- <_ReadyToRunCompositeBuildReferences
- Include="@(_ReadyToRunAssembliesToReference)"
- Exclude="@(_ReadyToRunCompositeBuildInput);@(_ReadyToRunCompositeUnrootedBuildInput)" />
+