[dotnet-run] implement "device" selection logic#51914
Merged
jonathanpeppers merged 12 commits intomainfrom Dec 4, 2025
Merged
Conversation
Context: https://github.com/dotnet/sdk/blob/5398e10de90dc9a27e0290ad55c2ae67360ea8be/documentation/specs/dotnet-run-for-maui.md ~~ Spec Changes ~~ **Added RuntimeIdentifier Support** - Examples to include `%(RuntimeIdentifier)` metadata (e.g., `android-arm64`, `ios-arm64`, `iossimulator-arm64`) - When a device provides a `%(RuntimeIdentifier)`, it will be passed as `-p:RuntimeIdentifier` to subsequent MSBuild steps (build, deploy, ComputeRunArguments, run) - `%(RuntimeIdentifier)` is optional but recommended **Added Binary Logs Documentation** - Added new section "Binary Logs for Device Selection" explaining: - When binlog files are created (when using `-bl:` with `dotnet run`) - The naming pattern: `<base-name>-dotnet-run-devices.binlog` ~~ Implementation ~~ **Renamed `TargetFrameworkSelector` to `RunCommandSelector`** - Expanded scope from just framework selection to handle both target framework and device selection - Made it a non-static class implementing `IDisposable` to: - Cache the MSBuild project instance across operations - Avoid loading/evaluating the project multiple times, except when global properties change - Properly manage MSBuild resources (ProjectCollection, Project, ProjectInstance) with `IDisposable` - Added `InvalidateGlobalProperties()` method to re-evaluate the project when needed with a `$(TargetFramework)` global property change. - Binary logger is owned by the `selector` instance and properly disposed. **Added Tests** - Mock test project (`DotnetRunDevices.csproj`) implements `ComputeAvailableDevices` target that returns hardcoded device items based on the target framework - Test project includes `GenerateDeviceInfo` target that runs during build when a device is selected: - Generates `DeviceInfo.cs` with constants for `$(Device)` and `$(RuntimeIdentifier)` properties - Writes to intermediate output directory before compilation - Test application prints these generated constants, allowing tests to verify that: - The correct device ID was passed to MSBuild - `$(RuntimeIdentifier)` was propagated correctly (when provided by device) - Multi-targeted apps can have different devices per framework
5048a76 to
43482d4
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements device selection logic for dotnet run, enabling MAUI and other workloads to target specific devices (emulators, simulators, physical devices). The implementation renames TargetFrameworkSelector to RunCommandSelector and expands its scope to handle both target framework and device selection with efficient project instance caching.
Key changes:
- Added
--deviceand--list-devicescommand-line options todotnet run - Implemented
RunCommandSelectorclass with device enumeration via MSBuild'sComputeAvailableDevicestarget - Added RuntimeIdentifier propagation from device metadata to subsequent build steps
- Comprehensive test coverage including multi-framework device selection scenarios
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Cli/dotnet/Commands/Run/RunCommandSelector.cs | New class handling both framework and device selection with project instance caching and IDisposable pattern |
| src/Cli/dotnet/Commands/Run/RunCommand.cs | Integrated device selection logic into run command workflow with proper binlog support |
| src/Cli/dotnet/Commands/Run/RunCommandParser.cs | Added DeviceOption and ListDevicesOption to command parser |
| src/Cli/dotnet/Commands/CliCommandStrings.resx | Added localization strings for device-related messages and prompts |
| src/Cli/dotnet/Commands/xlf/*.xlf | Updated localization files with new device-related string entries (state="new") |
| src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs | Added ComputeAvailableDevices MSBuild target constant |
| test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs | Comprehensive integration tests covering device selection scenarios |
| test/TestAssets/TestProjects/DotnetRunDevices/* | Test project with mock device enumeration and code generation |
| documentation/specs/dotnet-run-for-maui.md | Updated spec with RuntimeIdentifier metadata and binlog documentation |
| test/dotnet.Tests/CompletionTests/snapshots/* | Updated shell completion snapshots for new device options |
This was referenced Nov 26, 2025
Open
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
net8.0 target framework was crashing due to lack of Rosetta x64 -> arm64 translation. I think we can just use net9.0 + "current" instead
Seeing if this fixes macOS arm64
baronfel
reviewed
Dec 1, 2025
Member
Author
51 tasks
jonathanpeppers
added a commit
to dotnet/android
that referenced
this pull request
Dec 2, 2025
Context: dotnet/sdk#51337 Context: dotnet/sdk#51914 In 63f7cba, we added the `ComputeAvailableDevices` MSBuild target, which I was able to test end-to-end: D:\src\helloandroid> D:\src\dotnet\sdk\artifacts\bin\redist\Debug\dotnet\dotnet.exe run -bl Select a device to run on: > 0A041FDD400327 - Pixel 5 emulator-5554 - pixel 7 - api 36 Type to search Unfortunately, the AVD name is returned from `adb emu avd name`, which simply returns the property: > adb -s emulator-5554 shell getprop | grep avd_name [ro.boot.qemu.avd_name]: [pixel_7_-_api_36] We can call `TextInfo.ToTitleCase()`, replace underscores with spaces, and replace "Api" with "API" to make the AVD name more user-friendly. The only other alternative I considered was parsing the `~/.android/avd/<name>.ini` file to get the `displayname` property, but it would still require calling `adb emu avd name` to *get* the path to this `.ini` file. It felt more straightforward to just format the AVD name directly.
rolfbjarne
reviewed
Dec 3, 2025
jonathanpeppers
added a commit
to dotnet/android
that referenced
this pull request
Dec 3, 2025
Context: dotnet/sdk#51337 Context: dotnet/sdk#51914 In 63f7cba, we added the `ComputeAvailableDevices` MSBuild target, which I was able to test end-to-end: D:\src\helloandroid> D:\src\dotnet\sdk\artifacts\bin\redist\Debug\dotnet\dotnet.exe run -bl Select a device to run on: > 0A041FDD400327 - Pixel 5 emulator-5554 - pixel 7 - api 36 Type to search Unfortunately, the AVD name is returned from `adb emu avd name`, which simply returns the property: > adb -s emulator-5554 shell getprop | grep avd_name [ro.boot.qemu.avd_name]: [pixel_7_-_api_36] We can call `TextInfo.ToTitleCase()`, replace underscores with spaces, and replace "Api" with "API" to make the AVD name more user-friendly. The only other alternative I considered was parsing the `~/.android/avd/<name>.ini` file to get the `displayname` property, but it would still require calling `adb emu avd name` to *get* the path to this `.ini` file. It felt more straightforward to just format the AVD name directly.
baronfel
reviewed
Dec 4, 2025
baronfel
approved these changes
Dec 4, 2025
Member
baronfel
left a comment
There was a problem hiding this comment.
This looks very clean, thanks for taking this on! Excited to see the end to end get better for mobile app developers :)
Member
|
I'd still like someone from SDK engineering to review as well. |
MiYanni
approved these changes
Dec 4, 2025
jonathanpeppers
added a commit
that referenced
this pull request
Jan 21, 2026
Context: https://github.com/dotnet/sdk/blob/5398e10de90dc9a27e0290ad55c2ae67360ea8be/documentation/specs/dotnet-run-for-maui.md **Added RuntimeIdentifier Support** - Examples to include `%(RuntimeIdentifier)` metadata (e.g., `android-arm64`, `ios-arm64`, `iossimulator-arm64`) - When a device provides a `%(RuntimeIdentifier)`, it will be passed as `-p:RuntimeIdentifier` to subsequent MSBuild steps (build, deploy, ComputeRunArguments, run) - `%(RuntimeIdentifier)` is optional but recommended **Added Binary Logs Documentation** - Added new section "Binary Logs for Device Selection" explaining: - When binlog files are created (when using `-bl:` with `dotnet run`) **Renamed `TargetFrameworkSelector` to `RunCommandSelector`** - Expanded scope from just framework selection to handle both target framework and device selection - Made it a non-static class implementing `IDisposable` to: - Cache the MSBuild project instance across operations - Avoid loading/evaluating the project multiple times, except when global properties change - Properly manage MSBuild resources (ProjectCollection, Project, ProjectInstance) with `IDisposable` - Added `InvalidateGlobalProperties()` method to re-evaluate the project when needed with a `$(TargetFramework)` global property change. - Binary logger is owned by the `selector` instance and properly disposed. **Added Tests** - Mock test project (`DotnetRunDevices.csproj`) implements `ComputeAvailableDevices` target that returns hardcoded device items based on the target framework - Test project includes `GenerateDeviceInfo` target that runs during build when a device is selected: - Generates `DeviceInfo.cs` with constants for `$(Device)` and `$(RuntimeIdentifier)` properties - Writes to intermediate output directory before compilation - Test application prints these generated constants, allowing tests to verify that: - The correct device ID was passed to MSBuild - `$(RuntimeIdentifier)` was propagated correctly (when provided by device) - Multi-targeted apps can have different devices per framework
jonathanpeppers
added a commit
that referenced
this pull request
Jan 21, 2026
Context: https://github.com/dotnet/sdk/blob/5398e10de90dc9a27e0290ad55c2ae67360ea8be/documentation/specs/dotnet-run-for-maui.md **Added RuntimeIdentifier Support** - Examples to include `%(RuntimeIdentifier)` metadata (e.g., `android-arm64`, `ios-arm64`, `iossimulator-arm64`) - When a device provides a `%(RuntimeIdentifier)`, it will be passed as `-p:RuntimeIdentifier` to subsequent MSBuild steps (build, deploy, ComputeRunArguments, run) - `%(RuntimeIdentifier)` is optional but recommended **Added Binary Logs Documentation** - Added new section "Binary Logs for Device Selection" explaining: - When binlog files are created (when using `-bl:` with `dotnet run`) **Renamed `TargetFrameworkSelector` to `RunCommandSelector`** - Expanded scope from just framework selection to handle both target framework and device selection - Made it a non-static class implementing `IDisposable` to: - Cache the MSBuild project instance across operations - Avoid loading/evaluating the project multiple times, except when global properties change - Properly manage MSBuild resources (ProjectCollection, Project, ProjectInstance) with `IDisposable` - Added `InvalidateGlobalProperties()` method to re-evaluate the project when needed with a `$(TargetFramework)` global property change. - Binary logger is owned by the `selector` instance and properly disposed. **Added Tests** - Mock test project (`DotnetRunDevices.csproj`) implements `ComputeAvailableDevices` target that returns hardcoded device items based on the target framework - Test project includes `GenerateDeviceInfo` target that runs during build when a device is selected: - Generates `DeviceInfo.cs` with constants for `$(Device)` and `$(RuntimeIdentifier)` properties - Writes to intermediate output directory before compilation - Test application prints these generated constants, allowing tests to verify that: - The correct device ID was passed to MSBuild - `$(RuntimeIdentifier)` was propagated correctly (when provided by device) - Multi-targeted apps can have different devices per framework Update bash completion snapshot with trailing space
jonathanpeppers
added a commit
to dotnet/android
that referenced
this pull request
Jan 21, 2026
Context: dotnet/sdk#51337 Context: dotnet/sdk#51914 In 63f7cba, we added the `ComputeAvailableDevices` MSBuild target, which I was able to test end-to-end: D:\src\helloandroid> D:\src\dotnet\sdk\artifacts\bin\redist\Debug\dotnet\dotnet.exe run -bl Select a device to run on: > 0A041FDD400327 - Pixel 5 emulator-5554 - pixel 7 - api 36 Type to search Unfortunately, the AVD name is returned from `adb emu avd name`, which simply returns the property: > adb -s emulator-5554 shell getprop | grep avd_name [ro.boot.qemu.avd_name]: [pixel_7_-_api_36] We can call `TextInfo.ToTitleCase()`, replace underscores with spaces, and replace "Api" with "API" to make the AVD name more user-friendly. The only other alternative I considered was parsing the `~/.android/avd/<name>.ini` file to get the `displayname` property, but it would still require calling `adb emu avd name` to *get* the path to this `.ini` file. It felt more straightforward to just format the AVD name directly.
This was referenced Feb 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Context: https://github.com/dotnet/sdk/blob/5398e10de90dc9a27e0290ad55c2ae67360ea8be/documentation/specs/dotnet-run-for-maui.md
Spec Changes
Added RuntimeIdentifier Support
Examples to include
%(RuntimeIdentifier)metadata (e.g.,android-arm64,ios-arm64,iossimulator-arm64)When a device provides a
%(RuntimeIdentifier), it will be passed as-p:RuntimeIdentifierto subsequent MSBuild steps (build, deploy, ComputeRunArguments, run)%(RuntimeIdentifier)is optional but recommendedAdded Binary Logs Documentation
-bl:withdotnet run)<base-name>-dotnet-run-devices.binlogImplementation
Renamed
TargetFrameworkSelectortoRunCommandSelectorExpanded scope from just framework selection to handle both target framework and device selection
Made it a non-static class implementing
IDisposableto:IDisposableAdded
InvalidateGlobalProperties()method to re-evaluate the project when needed with a$(TargetFramework)global property change.Binary logger is owned by the
selectorinstance and properly disposed.Added Tests
Mock test project (
DotnetRunDevices.csproj) implementsComputeAvailableDevicestarget that returns hardcoded device items based on the target frameworkTest project includes
GenerateDeviceInfotarget that runs during build when a device is selected:DeviceInfo.cswith constants for$(Device)and$(RuntimeIdentifier)propertiesTest application prints these generated constants, allowing tests to verify that:
$(RuntimeIdentifier)was propagated correctly (when provided by device)