Skip to content

Conversation

@jonathanpeppers
Copy link
Member

Context: https://github.com/dotnet/sdk/blob/c164a9bc1246c48191fb780992530f0fe975141b/documentation/specs/dotnet-run-for-maui.md

Implements the DeployToDevice MSBuild target per the dotnet run spec for .NET MAUI scenarios. This target allows deploying an already-built app to a device without rebuilding, supporting the dotnet run workflow.

The target reuses existing deployment logic but skips the full build, enabling faster iteration when only deployment is needed e.g. --no-build.

Also consolidates $(SignAndroidPackageDependsOn), $(InstallDependsOnTargets), and $(UninstallDependsOnTargets) properties into BuildOrder.targets to keep all target dependency ordering in one place.

Adds test coverage to verify the target deploys successfully and the app can be launched via adb commands.

Context: https://github.com/dotnet/sdk/blob/c164a9bc1246c48191fb780992530f0fe975141b/documentation/specs/dotnet-run-for-maui.md

Implements the `DeployToDevice` MSBuild target per the `dotnet run` spec
for .NET MAUI scenarios. This target allows deploying an already-built
app to a device without rebuilding, supporting the `dotnet run`
workflow.

The target reuses existing deployment logic but skips the full build,
enabling faster iteration when only deployment is needed e.g.
`--no-build`.

Also consolidates `$(SignAndroidPackageDependsOn)`,
`$(InstallDependsOnTargets)`, and `$(UninstallDependsOnTargets)`
properties into `BuildOrder.targets` to keep all target dependency
ordering in one place.

Adds test coverage to verify the target deploys successfully and the
app can be launched via adb commands.
@jonathanpeppers
Copy link
Member Author

New test is working:

image

@jonathanpeppers jonathanpeppers marked this pull request as ready for review December 5, 2025 16:59
jonathanpeppers added a commit to dotnet/sdk that referenced this pull request Dec 5, 2025
Context: dotnet/android#10631

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

- Create `RunCommandSelector` once per run for framework/device
  selection and deployment

- Call `DeployToDevice` target if it exists in the project

- Reuse cached `ProjectInstance` for performance

- Add localized message for deployment failures

- Added tests
@jonathanpeppers jonathanpeppers merged commit cd88d9c into main Dec 8, 2025
57 of 59 checks passed
@jonathanpeppers jonathanpeppers deleted the dev/peppers/DeployToDevice branch December 8, 2025 15:27
jonathanpeppers added a commit to dotnet/sdk that referenced this pull request Dec 8, 2025
Context: dotnet/android#10631

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

- Create `RunCommandSelector` once per run for framework/device
  selection and deployment

- Call `DeployToDevice` target if it exists in the project

- Reuse cached `ProjectInstance` for performance

- Add localized message for deployment failures

- Added tests
jonathanpeppers added a commit to dotnet/sdk that referenced this pull request Dec 9, 2025
Context: dotnet/android#10631

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

- Create `RunCommandSelector` once per run for framework/device
  selection and deployment

- Call `DeployToDevice` target if it exists in the project

- Reuse cached `ProjectInstance` for performance

- Add localized message for deployment failures

- Added tests
jonathanpeppers added a commit to dotnet/sdk that referenced this pull request Dec 10, 2025
Context: dotnet/android#10631

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

- Create `RunCommandSelector` once per run for framework/device
  selection and deployment

- Call `DeployToDevice` target if it exists in the project

- Reuse cached `ProjectInstance` for performance

- Add localized message for deployment failures

- Added tests
jonathanpeppers added a commit to dotnet/sdk that referenced this pull request Dec 11, 2025
Context: dotnet/android#10631
Context: dotnet/android#10640

Add support for calling the `DeployToDevice` MSBuild target during
`dotnet run`. The target is invoked after the build step (or with
--no-build) to enable deployment to physical devices or emulators.

The main change here is to create the `RunCommandSelector` earlier in
the `RunCommand` execution, so that it can be used both for selecting
the target framework and device before build, and for invoking the
`DeployToDevice` target after build.

I tested this by making `DotnetRunDevices.csproj` include a target:

    <Target Name="DeployToDevice" DependsOnTargets="ResolveFrameworkReferences">
      <Message Text="DeployToDevice: Deployed to device $(Device) with RuntimeIdentifier $(RuntimeIdentifier)" Importance="high" />
    </Target>

Where `DependsOnTargets="ResolveFrameworkReferences"` mimics what can
happen in the Android workload.

I had to stop caching each `ProjectInstance` in `RunCommandSelector`,
as doing so can cause:

    》"artifacts\tmp\Debug\testing\ItDoesNotCall---A078BA19\DotnetRunDevices.csproj" (DeployToDevice target) (1) ->
    》(ResolveFrameworkReferences target) ->
    》  artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: The "ResolveFrameworkReferences" task failed unexpectedly.
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018: System.ArgumentException: An item with the same key has already been added. Key: Microsoft.NETCore.App
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.SpanToDictionary[TSource,TKey](ReadOnlySpan`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector, IEqualityComparer`1 comparer)
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolveFrameworkReferences.ExecuteCore() in src\Tasks\Microsoft.NET.Build.Tasks\ResolveFrameworkReferences.cs:line 29
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.NET.Build.Tasks.TaskBase.Execute() in src\Tasks\Common\TaskBase.cs:line 36
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
    》artifacts\bin\redist\Debug\dotnet\sdk\11.0.100-dev\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(410,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(TaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

The `ResolveFrameworkReferences` target will add duplicate
`Microsoft.NETCore.App` items within a `ProjectInstance` causing the
exception above.
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