-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[spec] better dotnet run extensibility for .NET MAUI
#51337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7207fdd
7655f8c
f86ea04
be8607e
478de96
b2b3be7
67d45c2
121d09a
c7699a2
527e5d1
4d9d5ff
a28b1b7
bac3b65
8b1e787
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,222 @@ | ||
| # `dotnet run` for .NET MAUI Scenarios | ||
|
|
||
| The current state of `dotnet run` for .NET MAUI projects is summarized | ||
| by this issue from 2021: | ||
|
|
||
| * [Figure out 'dotnet run' CLI experience for iOS and Android](https://github.com/dotnet/xamarin/issues/26) | ||
|
|
||
| The pain points being: | ||
|
|
||
| * iOS and Android use different properties to select a device, | ||
| emulator, or simulator. It is difficult for developers to make this | ||
| selection as you need to run platform-specific commands along with | ||
| complex MSBuild properties. | ||
|
|
||
| * Each platform has different behavior, regards to displaying console | ||
| output, etc. | ||
|
|
||
| * Using an MSIX with WindowsAppSDK doesn't support `dotnet run` at all, | ||
| relying completely on IDEs like Visual Studio. | ||
|
|
||
| * `dotnet run` does not have a concept of a "deploy" step. | ||
|
|
||
| This has become more relevant in the AI era, as someone is going to | ||
| expect AIs in "agent mode" to build and run their app. If the | ||
| command-line options are difficult, AIs will fail just as badly as | ||
| humans do today. | ||
|
|
||
| ## The `dotnet run` Pipeline | ||
|
|
||
| These are the high-level steps during `dotnet run`, that we would like | ||
| to make extensible for .NET MAUI (and future) scenarios. | ||
|
|
||
| * `restore`: unchanged | ||
|
|
||
| * "Pre-run evaluation" | ||
|
Comment on lines
+33
to
+35
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is also a "build" step right? |
||
|
|
||
| * If the project is multi-targeted, containing the | ||
| `$(TargetFrameworks)` property _and_ that property has more than | ||
| one item in it, and `-f` was not supplied... | ||
|
|
||
| * Prompt the user to select from a list of the | ||
| `$(TargetFrameworks)` | ||
|
|
||
| * Non-interactive mode will give a friendly error message, | ||
| suggesting to supply the `-f` property, listing available target | ||
| frameworks in the project. | ||
|
|
||
| * Once a `$(TargetFramework)` is selected, either from previous | ||
| steps or `-f`... | ||
|
|
||
| * If a `ComputeAvailableDevices` MSBuild target is available, provided by | ||
| the iOS or Android workload, etc. ... | ||
|
|
||
| * Call the MSBuild target, which returns a list of `@(Devices)` items... | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <!-- Android examples --> | ||
| <Devices Include="emulator-5554" Description="Pixel 7 - API 35" Type="Emulator" Status="Offline" /> | ||
| <Devices Include="emulator-5555" Description="Pixel 7 - API 36" Type="Emulator" Status="Online" /> | ||
| <Devices Include="0A041FDD400327" Description="Pixel 7 Pro" Type="Device" Status="Online" /> | ||
| <!-- iOS examples --> | ||
| <Devices Include="94E71AE5-8040-4DB2-8A9C-6CD24EF4E7DE" Description="iPhone 11 - iOS 18.6" Type="Simulator" Status="Shutdown" /> | ||
| <Devices Include="FBF5DCE8-EE2B-4215-8118-3A2190DE1AD7" Description="iPhone 14 - iOS 26.0" Type="Simulator" Status="Booted" /> | ||
| <Devices Include="23261B78-1E31-469C-A46E-1776D386EFD8" Description="My iPhone 13" Type="Device" Status="Unavailable" /> | ||
| <Devices Include="AF40CC64-2CDB-5F16-9651-86BCDF380881" Description="My iPhone 15" Type="Device" Status="Paired" /> | ||
| </ItemGroup> | ||
| ``` | ||
|
|
||
| _NOTE: each workload can decide which metadata values for `%(Type)` | ||
| and `%(Status)` are useful, filtering offline devices, etc. The output | ||
| above would be analogous to running `adb devices`, `xcrun simctl list | ||
| devices`, or `xcrun devicectl list devices`._ | ||
|
|
||
| * Continuing on... | ||
|
|
||
| * Prompt the user to select from this list of devices, emulators, | ||
| or simulators. | ||
|
|
||
| * Non-interactive mode will error, suggesting to supply the | ||
| `--device` switch. Listing the options returned by the | ||
| `ComputeAvailableDevices` MSBuild target. | ||
|
|
||
| * `build`: unchanged, but is passed `-p:Device`. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see the build step is mentioned here already. But doesn't it happen before the "pre-run evaluation"?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. today, yes - we're proposing changing that, either moving it entirely to the beginning or having a separate evaluation, based on the run-time requirements of the project being
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, it's unclear to me what would change during the "build" step when it's passed a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An iOS project is built differently depending on whether you're building for simulator or device. This means that you can either first select to run for the simulator or device, and then we'll present all the simulators or all the devices for you to choose from, or we can first present all the simulators + all the devices, and then we automatically build correctly depending on whether you chose a simulator or a device.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On Android, debug builds pick a single |
||
|
|
||
| * `deploy` | ||
|
|
||
| * If a `DeployToDevice` MSBuild target is available, provided by the | ||
| iOS or Android workload, etc. | ||
|
|
||
| * Call the MSBuild target, passing in the identifier for the selected | ||
| `-p:Device` global MSBuild property. | ||
|
|
||
| * This step needs to run, even with `--no-build`, as you may have | ||
| selected a different device. | ||
|
|
||
| * `ComputeRunArguments`: unchanged, but is passed `-p:Device`. | ||
|
|
||
| * `run`: unchanged. `ComputeRunArguments` should have set a valid | ||
| `$(RunCommand)` and `$(RunArguments)` using the value supplied by | ||
| `-p:Device`. | ||
|
|
||
| ## New `dotnet run` Command-line Switches | ||
|
|
||
| So far, it feels like no new subcommand is needed. In interactive | ||
| mode, `dotnet run` will now prompt to select a `$(TargetFramework)` | ||
| for all multi-targeted projects. Platform-specific projects like | ||
| Android, iOS, etc. will prompt for device selection. | ||
|
|
||
| `dotnet run --list-devices` will: | ||
|
|
||
| * Prompt for `$(TargetFramework)` for multi-targeted projects just | ||
| like when `--list-devices` is omitted. | ||
|
|
||
| * If there is a single `$(TargetFramework)`, skip to the next step. | ||
|
|
||
| * Call `ComputeAvailableDevices` if the MSBuild target exists, just | ||
| like when `--list-devices` is omitted. | ||
|
|
||
| * List the available targets by name, a unique identifier, and an | ||
| optional status of the device. | ||
|
|
||
| * Print a friendly message that says how to run `dotnet run` with | ||
| the new `--device` switch. | ||
|
|
||
| * If `ComputeAvailableDevices` does not exist in the project | ||
| (workload), it can print a friendly message and exit. | ||
|
|
||
| * `dotnet run --list-devices` will then basically exit early, never | ||
| running any build, deploy, `ComputeRunArguments`, or run steps. | ||
|
|
||
| A new `--device` switch will: | ||
|
|
||
| * bypass the device-selection portion of the `run` workflow described above | ||
|
|
||
| * Pass in the `-p:Device` global MSBuild property to all build, | ||
| deploy, `ComputeRunArguments`, or run steps. | ||
|
|
||
| * The iOS and Android workloads will know how to interpret `$(Device)` | ||
| to select an appropriate device, emulator, or simulator. | ||
|
|
||
| ## What about Launch Profiles? | ||
|
|
||
| The iOS and Android workloads ignore all | ||
| `Properties/launchSettings.json` files and do nothing with them. | ||
|
|
||
| WindowsAppSDK requires a launch profile to select between "packaged" | ||
| MSIX and an "unpackaged" .exe, and so we currently provide this in the | ||
| `dotnet new maui` project template: | ||
|
|
||
| ```json | ||
| { | ||
| "profiles": { | ||
| "Windows Machine": { | ||
| "commandName": "Project", | ||
| "nativeDebugging": false | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Or if you want to be "packaged": | ||
|
|
||
| ```json | ||
| { | ||
| "profiles": { | ||
| "Windows Machine": { | ||
| "commandName": "MsixPackage", | ||
| "nativeDebugging": false | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Launch profiles don't immediately look useful for iOS or Android, as | ||
| the identifier you'd put in here would be different per developer -- | ||
| you wouldn't want the value saved in source control. You could put a | ||
| generic selection like device vs emulator/simulator, but that isn't | ||
| addressing the problem we are interested in. Full launch profile | ||
| support for .NET MAUI projects may be interesting to address in the | ||
| future. | ||
|
|
||
| ## iOS and Android workload behavior | ||
|
|
||
| We will work to align as much behavior as possible between the | ||
| platforms. Most of this work will happen in the dotnet/android and | ||
| dotnet/macios repo, and would be orthogonal to the changes in the .NET | ||
| SDK. | ||
|
|
||
| ## macOS and MacCatalyst Behavior | ||
|
|
||
| `dotnet run` "just works" on macOS Desktop, because `$(RunCommand)` | ||
| can launch the app directly -- similar to console apps. | ||
|
|
||
| ## WindowsAppSDK Behavior | ||
|
|
||
| Running a `dotnet new maui` project works today because of the default | ||
| launch profile in "unpackaged" mode: | ||
|
|
||
| ```dotnetcli | ||
| > dotnet run -f net10.0-windows10.0.19041.0 | ||
| Using launch settings from D:\src\hellomaui\Properties\launchSettings.json... | ||
| ``` | ||
|
|
||
| To improve the behavior for "packaged" / MSIX, we could: | ||
|
|
||
| * Implement the `DeployToDevice` MSBuild target. | ||
|
|
||
| * `ComputeAvailableDevices` is not needed. | ||
|
|
||
| * Implement the `ComputeRunArguments` MSBuild target. | ||
|
|
||
| In the future, we can either add this logic into the .NET MAUI | ||
| workload or WindowsAppSDK itself. | ||
|
|
||
| ## Other frameworks: Avalonia, Uno, MonoGame, etc. | ||
|
|
||
| When these frameworks run on iOS or Android, they are basically using | ||
| the `ios` and `android` workloads _without_ .NET MAUI. Any iOS or | ||
| Android-specific behavior would apply to these project types in the | ||
| same way a `dotnet new android` or `dotnet new ios` project template | ||
| would. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently a big pain point. There doesn't seem to be an easy way to run packaged WinUI/UWP apps from command-line today?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also worth noting that we could make much use of that on
dotnet testside as well.WinAppSDK might be the first thing we could support in
dotnet test, but Android, iOS, Wasm could follow as well!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since, the
dotnet new mauiproject template is unpackaged right now, I think a future step is to see if we can improve WindowsAppSDK.Do you know if there are any issues filed about this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, our friendly neighborhood Matthew, of course!