Centralized Build in for .NET projects
- Dominant language
- C#
- Stars
- 6.3k
- Forks
- 991
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 196
Description
## Why
Move project builds from individual csproj executions into the AppHost runtime to:
- Defer builds until the AppHost starts, improving perceived startup.
- Build all projects together in parallel, reducing total build time.
- Let developers set per-project MSBuild properties from AppHost code/config instead of editing csproj files.
- Support bulding projects when they are not in a solution tracked by the IDE (see https://github.com/dotnet/aspire/issues/2154)
## Design Overview
- A single, hidden infrastructure resource in the AppHost performs one centralized build for all project resources.
- All project resources implicitly wait for this build to complete successfully before they start.
- Per-project MSBuild properties are attached to project resources (via annotations) and applied by the centralized build.
- The build runs from a working directory under `obj/` and is not shown in manifests or user-facing UIs.
## Public Surface (Top-level APIs)
Developers configure build intent on each project. The build orchestrator remains hidden.
- Project MSBuild properties:
- `WithMSBuildProperties(Action> configure)`
- `WithMSBuildProperties(IDictionary properties)`
- `WithMSBuildProperty(string name, string value)`
Behavior notes:
- Properties are merged per project; later values overwrite earlier ones for the same key.
- No new CLI or config surface is required beyond usual AppHost composition.
## Usage Examples (Hidden Resource)
Developers do not reference the build resource directly. It runs once, before projects start.
```csharp
// AppHost composition
var api = builder.AddProject("src/Api/Api.csproj")
.WithMSBuildProperty("TreatWarningsAsErrors", "true")
.WithMSBuildProperties(p =>
{
p["SelfContained"] = "true";
p["PublishSingleFile"] = "false";
});
var worker = builder.AddProject("src/Worker/Worker.csproj")
.WithMSBuildProperty("WarningsAsErrors", "NU1605;CS1591");
// The hidden build resource runs automatically before Api/Worker start.
```
## Behavioral Contract (What It Must Do)
- Discover all project resources in the AppHost model at startup.
- Collect per-project MSBuild properties attached via annotations.
- Produce a single aggregate build input that includes all project resources and their properties.
- Invoke one `dotnet build` for the aggregate, leveraging parallelism.
- Ensure all project resources wait for the centralized build and only start after it succeeds.
- Keep artifacts isolated under the AppHost’s `obj/` directory.
- Remain hidden (infra-only) and idempotent across compositions.
- Surface failures clearly and block dependent projects when the build fails.
- Respect standard `Configuration`/`Platform` defaults unless overridden by the developer.
## Scope and Non‑Goals
In scope:
- Build and restore for AppHost project resources.
- Per-project MSBuild property injection from AppHost code/config.
Out of scope (initial):
- Publish/pack/test orchestration, container builds, or non-MSBuild systems.
- Advanced validation/encoding of arbitrary property names/values.
## Acceptance Criteria
- Starting the AppHost triggers one centralized build before any project resource runs.
- Per-project MSBuild properties set in AppHost are honored by that build.
- The build executes in parallel and succeeds when individual projects build successfully.
- The build resource remains hidden from manifests and user-facing surfaces.
- Developers can add/update project-specific MSBuild properties without touching csproj files.
Contributor guide
Assessment
This issue has not been assessed yet.