Skip to content

Conversation

@rolfbjarne
Copy link
Member

This consists of two parts:

  • Add an MSBuild target that lists all the available devices (ComputeAvailableDevices), by returning them in a $(Devices) item group.
  • Add support for the $(Device) property to specify the device or simulator to use.

Regarding the device list, we'll filter the returned list by:

  • Platform (don't return an Apple TV simulator for an iOS app).
  • Minimum OS version (not return an iOS 18.0 device when the app's minimum OS version is 26.0).
  • Only devices that are actually available, as reported by devicectl or simctl.

References:

Fixes #23995.

…vailable to run on.

This consists of two parts:

* Add an MSBuild target that lists all the available devices (`ComputeAvailableDevices`), by returning them in a `$(Devices)` item group.
* Add support for the `$(Device)` property to specify the device or simulator to use.

Regarding the device list, we'll filter the returned list by:

* Platform (don't return an Apple TV simulator for an iOS app).
* Minimum OS version (not return an iOS 18.0 device when the app's minimum OS version is 26.0).
* Only devices that are actually available, as reported by `devicectl` or `simctl`.

References:

* dotnet/android#10576
* https://github.com/dotnet/sdk/blob/2b9fc02a265c735f2132e4e3626e94962e48bdf5/documentation/specs/dotnet-run-for-maui.md

Fixes #23995.
@rolfbjarne
Copy link
Member Author

@jonathanpeppers I think the spec needs to be updated so that the correct RuntimeIdentifier is set, depending on what the user chose - maybe the returned item group with the devices can have a 'RuntimeIdentifier' metadata that, if specified, is set for the subsequent build/run operation?

@rolfbjarne rolfbjarne requested a review from Copilot November 18, 2025 11:19
Copilot finished reviewing on behalf of rolfbjarne November 18, 2025 11:22
Copy link
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 adds support for listing available devices and simulators for iOS and tvOS apps, enabling device selection via the dotnet run --device command. The implementation follows the .NET SDK's device selection specification for MAUI-style device management.

Key Changes:

  • New GetAvailableDevices MSBuild task that queries devicectl and simctl to retrieve available physical devices and simulators
  • New ComputeAvailableDevices target that can be invoked to list all compatible devices
  • Property rename from _DeviceName to Device for specifying target devices

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tools/common/JsonExtensions.cs New utility class with JSON parsing extension methods for processing devicectl/simctl output
tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GetAvailableDevicesTest.cs Comprehensive test suite covering device filtering scenarios (platform, OS version, device family)
msbuild/Xamarin.MacDev.Tasks/Tasks/GetAvailableDevices.cs Main task implementation that queries devices, applies filters, and returns available devices
msbuild/Xamarin.Shared/Xamarin.Shared.targets Moved _AppBundleManifestPath property definition to allow access by GetAvailableDevices
msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj Added JsonExtensions.cs to the project
dotnet/targets/Xamarin.Shared.Sdk.targets Added ComputeAvailableDevices target and Device property with backward compatibility for _DeviceName
tests/common/shared-dotnet.mk Updated to use Device property instead of deprecated _DeviceName
docs/building-apps/build-targets.md Documentation for the new ComputeAvailableDevices target
docs/building-apps/build-properties.md Documentation for the new Device property

public ITaskItem [] Devices { get; set; } = Array.Empty<ITaskItem> ();

[Output]
public ITaskItem [] DiscardedDevices { get; set; } = Array.Empty<ITaskItem> ();
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

According to the coding guidelines, output properties should be initialized with [] instead of Array.Empty<ITaskItem>(). Change to:

public ITaskItem [] DiscardedDevices { get; set; } = [];

Copilot generated this review using guidance from repository custom instructions.
Queries and returns a list of available iOS or tvOS devices and simulators that can be used with `dotnet run`.

This target is called automatically by the .NET SDK's `dotnet run` command to
support device selection via the `--device` option. It returns a `@(Devices)``
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

There's a double backtick after @(Devices). It should be @(Devices) with no trailing backticks.

Suggested change
support device selection via the `--device` option. It returns a `@(Devices)``
support device selection via the `--device` option. It returns a `@(Devices)`

Copilot uses AI. Check for mistakes.

- **Description**: The name of the device (e.g., "iPhone 16 - iOS 26.0" for simulators, "My iPhone 16" for physical devices)
- **Type**: Either "Device" or "Simulator"
- **OSVersion**: The OS version if the device
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

Grammar error: should be "The OS version of the device" instead of "The OS version if the device".

Suggested change
- **OSVersion**: The OS version if the device
- **OSVersion**: The OS version of the device

Copilot uses AI. Check for mistakes.
The value can be anything the command-line tools `simctl` or `devicectl`
accept for the device name; this is typically either the UDID or the name of
the device. For example, for the device `My iOS Device` with UDID `0000-aaaabbbb`, use
either `-p:Device="My iOS Device"` or `-p:Device=0000-aaaabbbb`.
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

Inconsistent code formatting: The second command example should use backticks for consistency with the first example. Change -p:Device=0000-aaaabbbb to `-p:Device=0000-aaaabbbb`.

Copilot uses AI. Check for mistakes.
Target that queries available devices and simulators.
This target is called by 'dotnet run' to support device selection.
Returns @(Devices) items with metadata: ???????
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The comment states "Returns @(Devices) items with metadata: ???????" which appears to be a placeholder that was not filled in. The metadata should be documented here (Description, Type, OSVersion, UDID) similar to what's in the build-targets.md documentation.

Suggested change
Returns @(Devices) items with metadata: ???????
Returns @(Devices) items with metadata: Description, Type, OSVersion, UDID

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,107 @@
using System.ComponentModel.DataAnnotations;
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The using System.ComponentModel.DataAnnotations; directive appears to be unused. This namespace is typically used for validation attributes like [Required], but none of the methods in this file use these attributes.

Suggested change
using System.ComponentModel.DataAnnotations;

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +15
using System.Net;

Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

The using System.Net; directive appears to be unused in this file. Consider removing it to improve code clarity.

Suggested change
using System.Net;

Copilot uses AI. Check for mistakes.
public string AppBundleManifestPath { get; set; } = string.Empty;

[Output]
public ITaskItem [] Devices { get; set; } = Array.Empty<ITaskItem> ();
Copy link

Copilot AI Nov 18, 2025

Choose a reason for hiding this comment

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

According to the coding guidelines, output properties should be initialized with [] instead of Array.Empty<ITaskItem>(). Change to:

public ITaskItem [] Devices { get; set; } = [];

Copilot generated this review using guidance from repository custom instructions.
@vs-mobiletools-engineering-service2
Copy link
Collaborator

✅ [CI Build #a396aa9] Build passed (Build packages) ✅

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Collaborator

✅ [PR Build #a396aa9] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Collaborator

✅ [CI Build #a396aa9] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Collaborator

💻 [CI Build #a396aa9] Tests on macOS X64 - Mac Sonoma (14) passed 💻

All tests on macOS X64 - Mac Sonoma (14) passed.

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

💻 [CI Build #a396aa9] Tests on macOS M1 - Mac Monterey (12) passed 💻

All tests on macOS M1 - Mac Monterey (12) passed.

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

💻 [CI Build #a396aa9] Tests on macOS arm64 - Mac Sequoia (15) passed 💻

All tests on macOS arm64 - Mac Sequoia (15) passed.

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

💻 [CI Build #a396aa9] Tests on macOS M1 - Mac Ventura (13) passed 💻

All tests on macOS M1 - Mac Ventura (13) passed.

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2
Copy link
Collaborator

💻 [CI Build #a396aa9] Tests on macOS arm64 - Mac Tahoe (26) passed 💻

All tests on macOS arm64 - Mac Tahoe (26) passed.

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2
Copy link
Collaborator

🚀 [CI Build #a396aa9] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 117 tests passed 🎉

Tests counts

✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker: All 44 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 9 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 11 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 9 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 9 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

Pipeline on Agent
Hash: a396aa99e72f86f01eeb6f0133591320865e8dc4 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

Comment on lines -2410 to +2411
<DeviceName Condition="'$(DeviceName)' == ''">$(_DeviceName)</DeviceName>
<!-- Try to keep _DeviceName working for a while yet -->
<Device Condition="'$(Device)' == ''">$(_DeviceName)</Device>
Copy link
Member

Choose a reason for hiding this comment

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

Do you need to keep $(DeviceName) around, it's public? Maybe it's not really used/documented.

Comment on lines +2577 to +2578
Condition="'$(IsMacEnabled)' == 'true'"
SessionId="$(BuildSessionId)"
Copy link
Member

Choose a reason for hiding this comment

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

That is a question... Will this work on Windows? Ideally, it could, but that could be future PR.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants