# What Is the FileWrites Item Group in MSBuild Incremental Builds?

> Understand the FileWrites item group in MSBuild incremental builds. Learn how it helps dotnet clean remove generated files and ensures build consistency for efficient development.

- Repository: [.NET Platform/skills](https://github.com/dotnet/skills)
- Tags: internals
- Published: 2026-07-11

---

**The `FileWrites` item group is a built-in MSBuild mechanism that records every file created by custom targets, enabling `dotnet clean` to remove generated files and ensuring incremental build consistency.**

When building .NET projects, custom targets that generate code, assets, or intermediate files must track their outputs to maintain build hygiene. According to the `dotnet/skills` repository, the `FileWrites` item group serves as the official registry for these generated artifacts, bridging the gap between custom build logic and MSBuild's incremental build system.

## What Is the FileWrites Item Group?

The `FileWrites` item group is a built-in MSBuild collection that tracks every file produced by custom targets during a build. As documented in [`plugins/dotnet-msbuild/skills/incremental-build/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/incremental-build/SKILL.md) (lines 102-108), any file written by a target that isn't automatically tracked by MSBuild should be registered here to ensure proper cleanup and incremental behavior.

The item group works alongside `FileWritesShareable`, which handles files shared across multiple projects. While standard `FileWrites` entries are deleted during clean operations, shareable files are tracked but preserved if other projects still reference them.

## Why FileWrites Matters for Incremental Builds

### Clean Build Support

Without `FileWrites` registration, `dotnet clean` cannot remove generated files, leaving stale artifacts in output and intermediate folders. The [`plugins/dotnet-msbuild/skills/msbuild-antipatterns/references/incremental-build-inputs-outputs.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/msbuild-antipatterns/references/incremental-build-inputs-outputs.md) file (lines 27-30) highlights this as a critical requirement: generated files left behind can confuse subsequent builds and cause compilation errors from outdated inputs.

### Incremental Build Correctness

When a target writes files not declared in its `Outputs` attribute, MSBuild may skip the target during incremental checks, yet downstream targets still depend on those files. Registering outputs in `FileWrites` ensures the build state remains consistent even when targets produce side effects outside their declared inputs/outputs contract.

## How to Register Files in FileWrites

The standard pattern requires adding an `ItemGroup` inside the same target that generates the file. According to [`plugins/dotnet-msbuild/skills/including-generated-files/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/including-generated-files/SKILL.md) (lines 53-59), this registration must happen immediately after file creation.

```xml
<Target Name="MyGenerator"
        Inputs="@(SomeInputs)"
        Outputs="$(IntermediateOutputPath)generated.cs"
        BeforeTargets="CoreCompile">
  <WriteLinesToFile File="$(IntermediateOutputPath)generated.cs"
                    Lines="@(GeneratedLines)" />
  <ItemGroup>
    <FileWrites Include="$(IntermediateOutputPath)generated.cs" />
  </ItemGroup>
</Target>

```

For targets generating compile-time code:

```xml
<Target Name="GenerateVersionInfo"
        Inputs="$(MSBuildProjectFile)"
        Outputs="$(IntermediateOutputPath)VersionInfo.cs"
        BeforeTargets="CoreCompile">
  <WriteLinesToFile File="$(IntermediateOutputPath)VersionInfo.cs"
                    Lines="public static class VersionInfo { public const string Build = &quot;$(Version)&quot;; }" />
  <ItemGroup>
    <FileWrites Include="$(IntermediateOutputPath)VersionInfo.cs" />
    <Compile Include="$(IntermediateOutputPath)VersionInfo.cs" />
  </ItemGroup>
</Target>

```

## Handling Shared Generated Files

When multiple projects reference the same generated file, use `FileWritesShareable` instead of `FileWrites`. This prevents the file from being deleted during clean if another project still requires it.

```xml
<Target Name="GenerateSharedHelpers"
        Outputs="$(IntermediateOutputPath)SharedHelpers.cs">
  <!-- generation logic -->
  <ItemGroup>
    <FileWritesShareable Include="$(IntermediateOutputPath)SharedHelpers.cs" />
  </ItemGroup>
</Target>

```

## Internal Cleanup Mechanisms

The MSBuild engine uses internal targets to manage orphaned `FileWrites` entries. The [`plugins/dotnet-msbuild/skills/item-management/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/item-management/SKILL.md) file (lines 161-163) references a helper target that removes stale entries:

```xml
<Target Name="_CleanOrphanFileWrites"
        DependsOnTargets="_CleanPriorFileWrites">
  <ItemGroup>
    <_CleanOrphanFileWrites Include="@(_CleanPriorFileWrites)"
                             Exclude="@(_CleanCurrentFileWrites)" />
  </ItemGroup>
  <Delete Files="@(_CleanOrphanFileWrites)" />
</Target>

```

This ensures that files previously registered but no longer generated are properly cleaned up.

## Summary

- **`FileWrites`** is a built-in MSBuild item group that tracks files created by custom targets.
- Registering generated files enables `dotnet clean` to remove them, preventing stale artifacts.
- The [`plugins/dotnet-msbuild/skills/incremental-build/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/incremental-build/SKILL.md) documentation defines the registration pattern as adding an `ItemGroup` with `FileWrites` entries inside the generating target.
- **Incremental correctness** depends on registering side-effect files that aren't declared in target `Outputs`.
- Use **`FileWritesShareable`** for files referenced across multiple projects to prevent premature deletion.
- The [`plugins/dotnet-msbuild/skills/item-management/SKILL.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-msbuild/skills/item-management/SKILL.md) identifies missing `FileWrites` registration as a common antipattern in MSBuild projects.

## Frequently Asked Questions

### What happens if I don't register generated files in FileWrites?

If you omit `FileWrites` registration, `dotnet clean` cannot delete the generated files, leaving stale artifacts in your `obj` and `bin` folders. According to the `dotnet/skills` source analysis, these orphaned files can cause compilation errors in subsequent builds when the compiler picks up outdated generated code.

### When should I use FileWritesShareable instead of FileWrites?

Use `FileWritesShareable` when a generated file is shared across multiple projects in a solution. While standard `FileWrites` entries are always deleted during clean, shareable files are only removed when no other project references them, preventing build breaks in dependent projects.

### Can I register FileWrites outside the target that creates the file?

You should always register `FileWrites` inside the same target that generates the file, immediately after the file creation task. This ensures MSBuild correctly associates the file with the target execution and maintains accurate incremental build timestamps.

### Does FileWrites affect incremental build skipping behavior?

While `FileWrites` primarily supports clean operations, it indirectly affects incremental correctness by documenting side effects. MSBuild skips targets based on `Inputs` and `Outputs` timestamps, but registering files in `FileWrites` ensures the build system recognizes these artifacts exist, preventing "up-to-date" false positives when generating files outside the standard outputs contract.