Install any skill in seconds. Free to start, no credit card required.
Get Started Free →dotnet/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: l
Passed 21 of 22 test cases with the skill, and 18 of 22 without it.
3 fixed18 passed either way1 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 3 test cases the skill fixed. Same model, same prompt, with and without the skill.
We suspect Visual Studio's Fast Up-To-Date Check is incorrectly deciding our project is out of date and triggering rebuilds. Where in Visual Studio options can we enable detailed logging to see which specific file FUTDC considers out of date?
| Checked | Without skill | With skill |
|---|---|---|
| Directs to Tools -> Options -> Projects and Solutions -> SDK-Style Projects | Missed | Passed |
| Specifies setting Up-to-date Checks logging level to Verbose or higher | Passed | Passed |
The instructions your model reads when the skill loads.
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.
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.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.<!-- This target is incremental: skipped if Output is newer than all Inputs -->
<Target Name="Transform"
Inputs="@(TransformFiles)"
Outputs="@(TransformFiles->'$(OutputPath)%(Filename).out')">
<!-- work here -->
</Target>
<!-- This target always runs because it has no Inputs/Outputs -->
<Target Name="PrintMessage">
<Message Text="This runs every build" />
</Target>
Missing Inputs/Outputs on custom targets — Without both attributes, the target always runs. This is the single most common cause of unnecessary rebuilds.
Volatile properties in Outputs path — If the output path includes something that changes between builds (e.g., a timestamp, build number, or random GUID), MSBuild will never find the previous output and will always rebuild.
File writes outside of tracked Outputs — If a target writes files that aren't listed in its Outputs, MSBuild doesn't know about them. The target may be skipped (because its declared outputs are up to date), but downstream targets may still be triggered.
Missing FileWrites registration — Files created during the build but not registered in the FileWrites item group won't be cleaned by dotnet clean. Over time, stale files can confuse incremental checks.
Glob changes — When you add or remove source files, the item set (e.g., @(Compile)) changes. Since these items feed into Inputs, the set of inputs changes and triggers a rebuild. This is expected behavior but can be surprising.
Property changes — Properties that feed into Inputs or Outputs paths (e.g., $(Configuration), $(TargetFramework)) will cause rebuilds when changed. Switching between Debug and Release is a full rebuild by design.
NuGet package updates — Changing a package version updates project.assets.json and potentially many resolved assembly paths. This changes the inputs to ResolveAssemblyReferences and CoreCompile, triggering a rebuild.
Build server VBCSCompiler cache invalidation — The Roslyn compiler server (VBCSCompiler) caches compilation state. If the server is recycled (timeout, crash, or manual kill), the next build may be slower even though MSBuild's incremental checks pass, because the compiler must repopulate its in-memory caches.
test cases passed, vs 18 / 22 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.