Skip to content

Add MAUI build queue to serialize platform builds#15958

Open
jfversluis wants to merge 1 commit intomicrosoft:mainfrom
jfversluis:jfversluis/maui-build-queue
Open

Add MAUI build queue to serialize platform builds#15958
jfversluis wants to merge 1 commit intomicrosoft:mainfrom
jfversluis:jfversluis/maui-build-queue

Conversation

@jfversluis
Copy link
Copy Markdown
Member

@jfversluis jfversluis commented Apr 8, 2026

Summary

Adds build queue serialization for MAUI platform resources (Android, iOS, Mac Catalyst, Windows) that share the same project file. MSBuild cannot handle concurrent builds of the same project, causing intermittent file locking and XamlC assembly resolution failures. This PR serializes builds per-project using a semaphore.

Replaces #14945 (closed due to lost write access after dotnet to microsoft org migration). All review feedback from @davidfowl and @joperezr on #14945 has been addressed in this PR.

Key Changes

Build Queue (MauiBuildQueueEventSubscriber)

  • Subscribes to BeforeResourceStartedEvent for MAUI platform resources
  • Uses a per-project SemaphoreSlim(1,1) to serialize dotnet build commands
  • Shows Queued and Building states in the dashboard while waiting/building
  • Runs dotnet build as a subprocess with output piped to the resource logger
  • 10-minute build timeout prevents hung builds from blocking the queue

DCP Launch Override (ProjectLaunchArgsOverrideAnnotation)

  • New [Experimental("ASPIREMAUI001")] annotation overrides DCP default dotnet run with dotnet build /t:Run
  • MAUI requires build /t:Run because dotnet run does not support the Run target needed for device deployment
  • DCP still appends project path and --configuration automatically

Stop-While-Queued Support

  • Replaces the default stop command with a queue-aware version
  • Users can stop resources that are in Queued or Building state
  • Cancels the per-resource CTS, which unblocks the semaphore wait or kills the build process
  • Overrides DCP FailedToStart state to show Exited (user-initiated stop, not failure)

Post-Build Semaphore Hold

  • After pre-build succeeds, the semaphore is held until DCP dotnet build /t:Run reaches a stable state
  • Prevents concurrent MSBuild on shared dependency outputs (e.g., MauiServiceDefaults)
  • Replay-safe predicate skips stale snapshots from WatchAsync on resource restart

Review feedback addressed (from #14945)

  • Removed Assembly.GetEntryAssembly() configuration reading (davidfowl)
  • Removed IDisposable from MauiBuildQueueAnnotation (joperezr)
  • Added IOException catch for broken pipe in PipeOutputAsync
  • Documented TOCTOU race in stop command handler
  • Used KnownResourceStates constants instead of string literals
  • Marked ProjectLaunchArgsOverrideAnnotation with [Experimental("ASPIREMAUI001")]
  • Added ReleaseSemaphoreSafely() helper to guard against ObjectDisposedException
  • Replaced Task.Delay with deterministic WaitForBuildStartedAsync signals in tests

Testing

  • 94 unit tests covering queue serialization, cancellation, timeouts, restart, multi-project concurrency, and edge cases
  • Manual verification with the AspireWithMaui playground app

Files Changed

  • src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs - Core queue logic
  • src/Aspire.Hosting.Maui/Annotations/MauiBuildQueueAnnotation.cs - Per-project queue state
  • src/Aspire.Hosting.Maui/Annotations/MauiBuildInfoAnnotation.cs - Build metadata per resource
  • src/Aspire.Hosting/ApplicationModel/ProjectLaunchArgsOverrideAnnotation.cs - DCP launch override
  • src/Aspire.Hosting/Dcp/ExecutableCreator.cs - Reads override annotation
  • tests/Aspire.Hosting.Maui.Tests/MauiBuildQueueTests.cs - 94 tests

Copilot AI review requested due to automatic review settings April 8, 2026 12:44
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15958

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15958"

Copy link
Copy Markdown
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 introduces build-queue serialization for .NET MAUI platform resources that share the same project file, preventing concurrent MSBuild executions that can intermittently fail due to file locking and XamlC resolution issues.

Changes:

  • Added a per-project build queue (semaphore) and lifecycle subscriber that runs a pre-build step and shows Queued/Building dashboard states.
  • Added a ProjectLaunchArgsOverrideAnnotation and DCP support to override default dotnet run invocation (e.g., to dotnet build /t:Run for MAUI).
  • Added extensive unit tests plus small updates to the MAUI playground and package/test warning suppressions.

Reviewed changes

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

Show a summary per file
File Description
tests/Aspire.Hosting.Maui.Tests/MauiBuildQueueTests.cs Adds unit tests for queueing/serialization, cancellation, restart behavior, and related edge cases.
tests/Aspire.Hosting.Maui.Tests/Aspire.Hosting.Maui.Tests.csproj Suppresses ASPIREMAUI001 warning for the test project.
src/Aspire.Hosting/Dcp/DcpExecutor.cs Adds support for overriding the base dotnet command args via annotation.
src/Aspire.Hosting/ApplicationModel/ProjectLaunchArgsOverrideAnnotation.cs New annotation type used to override DCP-generated project launch args.
src/Aspire.Hosting.Maui/README.md Documents the MAUI build queue behavior and architecture.
src/Aspire.Hosting.Maui/MauiProjectResourceExtensions.cs Eagerly adds the per-project build queue annotation during AddMauiProject.
src/Aspire.Hosting.Maui/MauiPlatformHelper.cs Configures MAUI platform resources to use launch-args override and adds build metadata annotation.
src/Aspire.Hosting.Maui/MauiHostingExtensions.cs Registers the new MAUI build-queue event subscriber.
src/Aspire.Hosting.Maui/Lifecycle/MauiBuildQueueEventSubscriber.cs Implements queued/building states, pre-build subprocess, cancellation, and post-build semaphore hold.
src/Aspire.Hosting.Maui/Aspire.Hosting.Maui.csproj Suppresses ASPIREMAUI001 warning for the MAUI hosting package.
src/Aspire.Hosting.Maui/Annotations/MauiBuildQueueAnnotation.cs Adds per-project semaphore and cancellation tracking.
src/Aspire.Hosting.Maui/Annotations/MauiBuildInfoAnnotation.cs Adds per-resource build metadata used by the build-queue subscriber.
playground/AspireWithMaui/AspireWithMaui.MauiClient/MauiProgram.cs Updates service base address scheme to https+http:// for HTTP fallback.
playground/AspireWithMaui/AspireWithMaui.MauiClient/AspireWithMaui.MauiClient.csproj Updates several package references to stable versions.

@jfversluis jfversluis marked this pull request as draft April 8, 2026 12:52
@jfversluis jfversluis force-pushed the jfversluis/maui-build-queue branch 2 times, most recently from f9c78be to 55fbab8 Compare April 8, 2026 13:05
Adds build queue serialization for MAUI platform resources (Android, iOS,
Mac Catalyst, Windows) that share the same project file. MSBuild cannot
handle concurrent builds of the same project, causing intermittent file
locking and XamlC assembly resolution failures.

Key changes:
- MauiBuildQueueEventSubscriber: per-project SemaphoreSlim(1,1) serializes
  dotnet build commands with Queued/Building dashboard states
- ProjectLaunchArgsOverrideAnnotation: overrides DCP dotnet run with
  dotnet build /t:Run for MAUI device deployment
- Stop-while-queued support with queue-aware stop command replacement
- Post-build semaphore hold until DCP launch reaches stable state
- 94 unit tests covering serialization, cancellation, timeouts, restart

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jfversluis jfversluis force-pushed the jfversluis/maui-build-queue branch from 55fbab8 to c589809 Compare April 8, 2026 13:25
@jfversluis jfversluis marked this pull request as ready for review April 8, 2026 13:54
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.

2 participants