Skip to content

Make CoreCLR the default runtime for Debug builds#11169

Merged
simonrozsival merged 8 commits intomainfrom
dev/simonrozsival/coreclr-default-for-debug
Apr 22, 2026
Merged

Make CoreCLR the default runtime for Debug builds#11169
simonrozsival merged 8 commits intomainfrom
dev/simonrozsival/coreclr-default-for-debug

Conversation

@simonrozsival
Copy link
Copy Markdown
Member

This PR will switch the default runtime in .NET 11 P4 to CoreCLR. Both Release and Debug will now use CoreCLR.

Related to dotnet/macios#25050

Copilot AI review requested due to automatic review settings April 21, 2026 09:15
@simonrozsival simonrozsival added the Area: CoreCLR Issues that only occur when using CoreCLR. label Apr 21, 2026
@simonrozsival simonrozsival added this to the .NET 11 milestone Apr 21, 2026
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 changes the .NET for Android SDK defaults so Debug builds no longer force UseMonoRuntime=true, which makes CoreCLR the default runtime for both Debug and Release builds (unless a project explicitly opts into MonoVM or NativeAOT).

Changes:

  • Remove the Debug-only default UseMonoRuntime=true in SDK default properties.
  • As a result, _AndroidRuntime falls back to CoreCLR when PublishAot is not enabled and UseMonoRuntime isn’t explicitly set.

MSTest's VSTest bridge resolves test assembly paths via
Assembly.Location, which returns empty string on CoreCLR Android
with fast-deploy (assemblies are memory-mapped). This causes
MSTestDiscovererHelpers.AreValidSources() to fail with
NotSupportedException.

Setting EmbedAssembliesIntoApk=true ensures assemblies are embedded
in the APK so Assembly.Location returns a valid path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival
Copy link
Copy Markdown
Member Author

Root Cause Analysis: DotNetNewAndroidTest failure

Summary

With CoreCLR as the default runtime for Debug builds, the androidtest template fails because MSTest requires Assembly.Location to return a valid file path, but CoreCLR returns "" for assemblies loaded via fast-deploy.

Detailed call chain

  1. This PR removes <UseMonoRuntime>true</UseMonoRuntime> for Debug builds → CoreCLR becomes the default runtime
  2. Debug builds use fast-deploy (EmbedAssembliesIntoApk=false by default)
  3. With fast-deploy, assemblies are pushed to the device's override directory and loaded via Host::clr_external_assembly_probe (host.cc:91), which memory-maps them
  4. Assembly.Location returns "" for memory-mapped assemblies on CoreCLR (MonoVM resolves a file path even for fast-deploy assemblies)
  5. MSTest's SynchronizedSingleSessionVSTestBridgedTestFramework.ExecuteRequestAsync calls _getTestAssemblies().Select(x => x.Location).ToArray()
  6. MSTestDiscovererHelpers.AreValidSources() checks that paths end with .dll or .exe
  7. Empty string fails validation → throw new NotSupportedException(Resource.SourcesNotSupported)

Fix

Set <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> in the androidtest template. This forces assemblies to be packaged inside the APK and extracted to a known filesystem path, making Assembly.Location return a valid path. Disabling fast-deploy for test projects is acceptable since they are not frequently iterated on during development.

Upstream issue

This is fundamentally an MSTest limitation — it should not rely on Assembly.Location being a valid file path. A bug should be filed on microsoft/testfx.

simonrozsival and others added 5 commits April 21, 2026 10:40
…allback trimming (#11168)

## Summary

Fixes a bug in the trimmable typemap UCO (UnmanagedCallersOnly) wrapper generator where the callback member reference used `byte` (uint8) for JNI boolean returns, but MCW-generated `n_*` callback methods use `sbyte` (int8).

## The Bug

In ECMA-335 metadata, `int8` and `uint8` are different types for method signature matching. When ILLink performed its reachability analysis, it could not resolve the cross-assembly member reference from the typemap DLL to `n_*` methods in `Mono.Android.dll` because the return type did not match. ILLink then treated these `n_*` callbacks as unreachable and trimmed them.

At runtime, this caused `MissingMethodException` for methods like `IHostnameVerifierInvoker.n_Verify_Ljava_lang_String_Ljavax_net_ssl_SSLSession_`, which cascaded into a SIGSEGV on a background thread.

## The Fix

- Added `EncodeClrTypeForCallback()` to `JniSignatureHelper` that uses `sbyte` for JNI boolean, matching the MCW `_JniMarshal_*_B` delegate convention.
- Updated `EmitUcoMethod()` in `TypeMapAssemblyEmitter` to use the callback-specific encoding when constructing the member reference to `n_*` methods.
- The UCO wrapper's own method signature continues to use `byte` (correct for JNI ABI / `[UnmanagedCallersOnly]`).
Pass UseMonoRuntime=true/false via build parameters to toggle runtime.
For CoreCLR, also pass EmbedAssembliesIntoApk=true as a workaround
for MSTest's Assembly.Location requirement with fast-deploy.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DotNetCLI.Build() adds /p: via GetDefaultCommandLineArgs, but
StartRun() passes parameters raw. Without /p:, dotnet run receives
bare 'UseMonoRuntime=True' which breaks the command.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment on lines +2249 to +2256
bool useMonoRuntime = runtime == AndroidRuntime.MonoVM;
var buildParameters = new List<string> {
$"UseMonoRuntime={useMonoRuntime}",
};
if (runtime == AndroidRuntime.CoreCLR) {
// TODO: MSTest requires Assembly.Location, which returns empty with fast-deploy on CoreCLR. Remove when fast-deploy is fixed.
buildParameters.Add ("EmbedAssembliesIntoApk=true");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm, the CoreCLR test fails:

Image

Copy link
Copy Markdown
Member

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member Author

@simonrozsival simonrozsival Apr 22, 2026

Choose a reason for hiding this comment

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

the PR that will fix this looks solid: microsoft/testfx#7772

MSTest's VSTest bridge uses Assembly.Location to resolve test sources,
which returns empty on CoreCLR Android. Assert.Ignore with link to
tracking issue.

See #11174

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@jonathanpeppers jonathanpeppers left a comment

Choose a reason for hiding this comment

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

I ignored the one test for now, if everything looks green, feel free to merge.

@simonrozsival simonrozsival merged commit 4c73c8a into main Apr 22, 2026
3 checks passed
@simonrozsival simonrozsival deleted the dev/simonrozsival/coreclr-default-for-debug branch April 22, 2026 15:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: CoreCLR Issues that only occur when using CoreCLR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants