incremental-build
Guide for optimizing MSBuild incremental builds. USE FOR: builds slower than expected on subsequent runs, 'nothing changed but it rebuilds anyway', diagnosing why targets re-execute unnecessarily, fixing broken no-op builds. Covers 8 common causes: missing Inputs/Outputs on custom targets, volatile properties in output paths (timestamps/GUIDs), file writes outside tracked Outputs, missing FileWrites registration, glob changes, Visual Studio Fast Up-to-Date Check (FUTDC) issues. Key diagnostic: look for 'Building target completely' vs 'Skipping target' in binlog. DO NOT USE FOR: first-time buil
npx skills add dotnet/skills --skill incremental-build --agent claude-code
Same command for any agent — swap --agent for codex, cursor, copilot.
Weekly change comes from our own snapshots, not the repository page — it measures attention, not adoption.
## How MSBuild Incremental Build Works MSBuild's incremental build mechanism allows targets to be skipped when their outputs are already up to date, dramatically reducing build times on subsequent runs. - **Targets with `Inputs` and `Outputs` attributes**: MSBuild compares the timestamps of all files listed in `Inputs` against all files listed in `Outputs`. If every output file is newer than every input file, the target is skipped entirely. - **Without `Inputs`/`Outputs`**: The target runs every time the build is invoked. This is the default behavior and the most common cause of slow incremental builds. - **`Incremental` attribute on targets**: Targets can explicitly opt in or out of incremental behavior. Setting `Incremental="false"` forces the target to always run, even if `Inputs` and `Outputs` are specified. - **Timestamp-based comparison**: MSBuild uses file system timestamps (last write time) to determine staleness. It does not use content hashes. This means touching a file (updating its timestamp without changing content) will trigger a rebuild. ```xml <!-- This target is incremental: skipped if Output is newer than all Inputs --> <Target Name="Transform" Inputs="@(Transform
- How MSBuild Incremental Build Works
- Why Incremental Builds Break (Top Causes)
- Diagnosing "Why Did This Rebuild?"
- Step-by-step using binlog
- Primary: binlog MCP (preferred)
- Fallback: text-log replay (when MCP is unavailable)
- Additional diagnostic techniques
- FileWrites and Clean Build
- Pattern for registering generated files
- Visual Studio Fast Up-to-Date Check
- Making Custom Targets Incremental
- Common mistakes to avoid
- Performance Summary and Preprocess
- Common Fixes
dotnet build /bl:first.binlog dotnet build /bl:second.binlog dotnet msbuild second.binlog -noconlog -fl -flp:v=diag;logfile=second-full.log;performancesummary grep 'Building target\|Target.*was not skipped' second-full.log grep "is newer than output" second-full.log dotnet build /clp:PerformanceSummary dotnet msbuild /pp:preprocess.xml
What does the incremental-build skill do?
Guide for optimizing MSBuild incremental builds. USE FOR: builds slower than expected on subsequent runs, 'nothing changed but it rebuilds anyway', diagnosing why targets re-execute unnecessarily, fixing broken no-op builds. Covers 8 common causes: missing Inputs/Outputs on custom targets, volatile properties in output paths (timestamps/GUIDs), file writes outside tracked Outputs, missing FileWrites registration, glob changes, Visual Studio Fast Up-to-Date Check (FUTDC) issues. Key diagnostic: look for 'Building target completely' vs 'Skipping target' in binlog. DO NOT USE FOR: first-time buil
How do I install it?
Run `npx skills add dotnet/skills --skill incremental-build --agent claude-code` — it drops the skill into your project so the agent can pick it up. Swap the --agent value for codex, cursor or copilot if you use one of those.
Where does this skill come from?
From dotnet/skills, a repository with 4,927 stars. We read it straight from the repository tree rather than a submitted listing, so what you see here is what is actually published.
Is a popular skill a good skill?
Not necessarily. Stars measure attention, not adoption — a repository can trend for a week and be abandoned. That is why we show the weekly change from our own snapshots next to the total, instead of a single flattering number.