Infra, Ops & WorkflowSûr8080/100

Integrating SDK And Msbuild (.NET)

Guides work on the SDK-MSBuild integration boundary. Consult when authoring or modifying SDK targets, working on dotnet CLI to MSBuild invocation, handling project-reference protocol, coordinating cross-repo changes with dotnet/sdk, debugging property resolution or import ordering, working on restore/build/publish/pack target chains, or dealing with Directory.Build.props/targets interaction.

ou envoie-le directement à ton agent.

Installer dans ton projet

$ curl -fsSL https://arboristhree.xyz/cli/install-skill.mjs -o /tmp/arboris-install-skill.mjs && node /tmp/arboris-install-skill.mjs integrating-sdk-and-msbuild__dotnet-dotnet__src-msbuild-github-skills-debbbca7ce04
.NET
dotnet/dotnet
Contenu à copier
---
name: integrating-sdk-and-msbuild
description: 'Guides work on the SDK-MSBuild integration boundary. Consult when authoring or modifying SDK targets, working on dotnet CLI to MSBuild invocation, handling project-reference protocol, coordinating cross-repo changes with dotnet/sdk, debugging property resolution or import ordering, working on restore/build/publish/pack target chains, or dealing with Directory.Build.props/targets interaction.'
argument-hint: 'Describe the SDK integration scenario or cross-repo coordination need.'
metadata:
  origin: .NET
---

# SDK-MSBuild Integration Patterns

MSBuild operates as a component within the .NET SDK. This boundary is the most complex integration point in the .NET build stack, spanning MSBuild (engine), SDK (target implementations), NuGet (restore), and Roslyn (compilation).

## The Evaluation Boundary

Understanding MSBuild's evaluation order is critical for SDK target authoring:

```
1. Environment variables
2. Global properties (from CLI: -p:Foo=Bar)
3. Project-level properties (file order, with imports):
   ┌─ Sdk.props (SDK defaults)
   ├─ Directory.Build.props (user overrides BEFORE project)
   ├─ <Project> properties (the .csproj itself)
   ├─ Directory.Build.targets (user overrides AFTER project)
   └─ Sdk.targets (SDK target definitions)
4. Item definitions
5. Items (including SDK default globs)
```

### Key Import Order Rules

- **SDK props import BEFORE user project** — SDK defaults can be overridden by the user
- **SDK targets import AFTER user project** — SDK targets see user-specified properties
- **`Directory.Build.props` is imported from `Microsoft.Common.props` as an early user extension point after core defaults are computed** — use it for solution-wide customization
- **Property defaults set in SDK must not override user-specified values** — always use `Condition="'$(Prop)' == ''"`

```xml
<!-- CORRECT: SDK default that respects user override -->
<OutputType Condition="'$(OutputType)' == ''">Library</OutputType>

<!-- WRONG: Unconditional set clobbers user's .csproj -->
<OutputType>Library</OutputType>
```

## Restore and Build Separation

**Restore and Build must never run in the same evaluation.** The restore phase generates `.g.props` and `.g.targets` files that must be imported during evaluation — but they don't exist until restore completes.

- `dotnet build` implicitly runs restore then build as **separate invocations**
- `dotnet build --no-restore` skips restore, assuming it already happened
- Running both targets in one invocation (`/t:Restore;Build`) is a known anti-pattern that causes intermittent failures

## Project Reference Protocol

The project-reference protocol spans MSBuild, SDK, and NuGet. It is the most complex integration boundary.

### How It Works

1. Outer build dispatches to `_GetProjectReferenceTargetFrameworkProperties` to determine inner build parameters
2. Inner build runs with the resolved `TargetFramework` (singular) for each referenced project
3. `GetTargetPath` returns the output assembly for the referencing project to consume

### Rules

- Protocol changes must be coordinated across MSBuild, SDK, and NuGet teams
- Multi-targeting projects (`<TargetFrameworks>`) dispatch multiple inner builds
- The outer build must not assume a single target framework
- `SetTargetFramework` is how the outer build communicates the chosen framework to inner builds

## Target Authoring in SDK Context

### Extension Points

SDK provides well-known extension points for targets:

| Extension Point | Use For |
|----------------|---------|
| `$(BuildDependsOn)` | Adding to the Build chain |
| `$(CompileDependsOn)` | Pre-compilation steps |
| `$(PublishDependsOn)` | Publish pipeline additions |
| `$(PackDependsOn)` | NuGet pack pipeline additions |
| `BeforeTargets="Build"` | Use sparingly; prefer `DependsOnTargets` |

### Ordering Rules

1. **Use `DependsOnTargets` for required predecessors** — it's explicit and predictable
2. **`BeforeTargets`/`AfterTargets` should be used sparingly** — they create implicit ordering that's hard to debug
3. **Incremental build targets need precise `Inputs` and `Outputs`** — incorrect declarations cause either rebuild-every-time or stale-output bugs
4. **Test with multi-targeting** — target chains execute once per `TargetFramework` in the inner build

## Cross-Repo Coordination

Changes that touch the MSBuild-SDK boundary often require coordinated PRs:

1. **MSBuild engine change** → may need SDK target updates
2. **SDK target change** → may need MSBuild API additions
3. **NuGet restore change** → affects both MSBuild evaluation and SDK targets

### Coordination Protocol

- File an issue in both repos describing the cross-cutting change
- Land the MSBuild change first (lower in the stack)
- Update SDK to consume the new MSBuild via dependency flow
- Test end-to-end with the SDK's MSBuild integration tests

## Design-Time Builds

Visual Studio uses design-time builds with different target contracts:

- Design-time builds call `ResolveProjectReferences` but not `Build`
- They set `$(DesignTimeBuild)=true` and `$(BuildingProject)=false`
- Targets that should not run during design-time must check these properties
- Design-time builds must be fast — avoid expensive I/O or compilation

## Common Integration Bugs

| Symptom | Likely Cause |
|---------|-------------|
| Property has wrong value | Import ordering — check if SDK prop overrides user setting |
| Target runs in wrong order | Missing `DependsOnTargets` declaration |
| Build works, restore fails | Evaluation-time dependency on restore-generated files |
| Works single-target, fails multi-target | Target assumes single `$(TargetFramework)` |
| CLI build works, VS build fails | Design-time build target contract violation |
Colle ce Markdown dans ton agent ou utilise les boutons ci-dessus pour l’écrire dans ton projet.

Ce que fait Integrating SDK And Msbuild (.NET)

**SDK props import BEFORE user project** — SDK defaults can be overridden by the user
**SDK targets import AFTER user project** — SDK targets see user-specified properties
**`Directory.Build.props` is imported from `Microsoft.Common.props` as an early user extension point after core defaults are computed** — use it for solution-wide customization
**Property defaults set in SDK must not override user-specified values** — always use `Condition="'$(Prop)' == ''"`

Comment utiliser Integrating SDK And Msbuild (.NET)

1
Copie le prompt
Un clic copie le prompt packagé (ou l'envoie à ton agent).
2
L'agent installe le skill
Il ajoute le SKILL.md et ses ressources à ton projet.
3
Activation automatique
Le skill s'active dès que le contexte correspond.

Déclencheurs pour Integrating SDK And Msbuild (.NET)

Dis simplement à ton agent quelque chose comme :

Applique le skill integrating-sdk-and-msbuild__dotnet-dotnet__src-msbuild-github-skills-debbbca7ce04 à cette tâche
Utilise integrating-sdk-and-msbuild__dotnet-dotnet__src-msbuild-github-skills-debbbca7ce04 pour améliorer cette implémentation
Passe en revue ce sujet avec integrating-sdk-and-msbuild__dotnet-dotnet__src-msbuild-github-skills-debbbca7ce04

Skills liés à Integrating SDK And Msbuild (.NET)

Add CLI Command (.NET)
Add or change a dotnet CLI command, subcommand, or option across the relevant CLI projects. USE FOR: adding or changing a dotnet CLI command/subcommand, adding a new Option<T> or Argument<T>, registering a subcommand in the command tree, changing an option's help description or a command's runtime message, wiring a command parser, or updating --help output.
Add Dotnet Aot Command (.NET)
Add, enable, or review a dotnet CLI command or feature in the Native AOT CLI (src/Cli/dotnet-aot) and prove its compatibility. USE FOR: migrating a command or option to AOT, reviewing an AOT migration PR, defining conservative eligibility and managed fallback, changing AotSourceFiles.props or AotDependencies.props, validating AOT/managed parity, NativeAOT-publishing tests, checking binary-size impact, or using the dn harness and separated SDK layout. DO NOT USE FOR: resolving IL trim/AOT analyzer warnings alone (use dotnet-aot-compat), running dotnet.Tests incrementally (use incremental-test), or pure managed CLI work.
Add Net Analyzer (.NET)
Add, port, or change a .NET code analysis rule (CA####) under src/Microsoft.CodeAnalysis.NetAnalyzers. USE FOR: implementing a new CA analyzer and its code fixer, porting a rule or PR from the retired dotnet/roslyn-analyzers repo, allocating a diagnostic ID from DiagnosticCategoryAndIdRanges.txt, choosing RuleLevel/severity/category, wiring resx + xlf strings, recording the rule in AnalyzerReleases.Unshipped.md, regenerating the analyzer documentation/sarif files, and writing MSTest analyzer/code-fix tests with the VerifyCS/VerifyVB harness. DO NOT USE FOR: NETSDK#### MSBuild diagnostics (src/Tasks), CS####/BC#### compiler diagnostics or IDE#### analyzers (dotnet/roslyn), or CONTAINER#### diagnostics (src/Containers).