Forward debugger ports for dotnet run - #12578
Conversation
Route both ComputeRunArguments wait modes through Microsoft.Android.Run, add generic ADB TCP mappings, and preserve legacy Run and _Run behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f13f2ddd-fcd8-4c74-a37a-fdf6855b0d36
There was a problem hiding this comment.
Pull request overview
This PR fixes dotnet run / dotnet watch Android debugger port-forwarding by ensuring the ComputeRunArguments launch path always goes through Microsoft.Android.Run, where ADB port mappings can be established before launching the app (including the WaitForExit=false/non-blocking mode).
Changes:
- Route both
WaitForExit=trueandWaitForExit=falseComputeRunArgumentsexecution throughMicrosoft.Android.Run, using--no-wait/--no-wake-devicefor the non-blocking mode. - Add generic repeatable
--forward-port/--reverse-portoptions toMicrosoft.Android.Run, and haveComputeRunArgumentsemit a forward mapping whenAndroidAttachDebugger=trueandAndroidDebuggerServer=true. - Add a focused regression test asserting that
ComputeRunArgumentsincludes the expected--forward-portarguments (and suppresses legacy--debugger-*args).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildOrderTests.cs | Adds regression coverage to validate ComputeRunArguments emits generic port-forwarding args in both wait and no-wait modes. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Application.targets | Updates ComputeRunArguments to consistently invoke Microsoft.Android.Run and pass through forwarding + no-wait/no-wake flags as needed. |
| src/Microsoft.Android.Run/Program.cs | Implements --no-wait, plus repeatable --forward-port / --reverse-port configuration and applies the mappings before app launch. |
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
⚠️ Needs Changes
Findings: 0 errors · 0 warnings · 1 suggestion
The implementation consistently routes both wait modes through Microsoft.Android.Run and preserves the legacy debugger-port direction. Please add runner-level coverage for the new generic port-mapping CLI surface; the current test only verifies MSBuild argument composition.
CI currently has 37 successful checks, with 7 emulator lanes still running and the aggregate build queued.
Generated by Android PR Reviewer for #12578 · gpt56 · 117.9 AIC · ⌖ 8.86 AIC · ⊞ 25.7K
Comment /review to run again
| !int.TryParse (ports [1], out int destination) || | ||
| source is < 1 or > 65535 || | ||
| destination is < 1 or > 65535) { | ||
| throw new OptionException ("Expected two TCP ports between 1 and 65535 in SOURCE:DESTINATION format.", option); |
There was a problem hiding this comment.
🤖 💡 Testing — The added test only inspects the generated MSBuild argument string, so neither new runner option is exercised. Invalid/boundary mappings, repeated mappings, and adb reverse command construction can regress unnoticed. Please add focused runner-level coverage around port parsing and command generation for both forward and reverse mappings.
Rule: Test edge cases
Summary
WaitForExit=trueandWaitForExit=falseComputeRunArgumentspaths throughMicrosoft.Android.RunAndroidSdbTargetPort/AndroidSdbHostPortvalues as a generic ADB forward mapping whenAndroidAttachDebugger=trueandAndroidDebuggerServer=true--forward-portand--reverse-portrunner optionsRun,_Run,RunActivity, Mono debugger, and JDWP behavior unchangedBackground
We are testing the debugger connection through
dotnet watch, and these changes facilitate that scenario.dotnet watchlaunches adotnet run --no-buildchild process, which executes the command returned byComputeRunArguments; it does not invoke_Run. The debugger properties therefore reached MSBuild, but the legacy_Runtarget that establishedadb forwardnever executed.This change establishes the requested port mapping in
Microsoft.Android.Runbefore launching the application. BothWaitForExit=trueandWaitForExit=falseuse the runner, so forwarding works for directdotnet runand the child process launched bydotnet watchwithout changing the legacy MSBuildRun/_Runpaths.CoreCLR debugger configuration remains owned by vscode-maui, which ships the native debugger libraries and configures the runtime. See DevDiv/vscode-maui PR 716837 for that implementation.
A broader cleanup is intentionally deferred to .NET 12: #12577 tracks unifying the
Runtarget behavior, deleting_Run, and removing obsolete Mono-specific launch paths.Validation
Microsoft.Android.Runfornet10.0Microsoft.Android.Sdk.Application.targetsas XMLComputeRunArgumentscoverage for waiting, no-wait, debugger-server, and forwarding behaviorThe full
Xamarin.Android.Build.Testsassembly was not run because this checkout does not contain the locally built Android SDK/reference packs.