Share via


How To: Build Incrementally 

When you build a large project, it is important that previously built components that are still up-to-date are not rebuilt. If all targets are built every time, each build will take a long time to complete. To enable incremental builds (builds in which only those targets that have not been built before or targets that are out of date, are rebuilt), the Microsoft Build Engine (MSBuild) can compare the timestamps of the input files with the timestamps of the output files and determine whether to skip, build, or partially rebuild a target. However, there must be a one-to-one mapping between inputs and outputs. You can use transforms to enable targets to identify this direct mapping. For more information on transforms, see MSBuild Transforms.

Specifying Inputs and Outputs

A target can be built incrementally if the inputs and outputs are specified in the project file.

To specify inputs and outputs for a target

  • Use the Inputs and Outputs attributes of the Target element. For example:

    <Target Name="Build"
        Inputs="@(CSFile)"
        Outputs="hello.exe">
    

MSBuild can compare the timestamps of the input files with the timestamps of the output files and determine whether to skip, build, or partially rebuild a target. In the following example, if any file in the @(CSFile) item collection is newer than the hello.exe file, MSBuild will run the target; otherwise it will be skipped:

<Target Name="Build" 
    Inputs="@(CSFile)" 
    Outputs="hello.exe">

    <Csc
        Sources="@(CSFile)" 
        OutputAssembly="hello.exe"/>
</Target>

When inputs and outputs are specified in a target, either each output can map to only one input or there can be no direct mapping between the outputs and inputs. In the previous Csc task, for example, the output, hello.exe, cannot be mapped to any single input – it depends on all of them.

Note

A target in which there is no direct mapping between the inputs and outputs will always build more often than a target in which each output can map to only one input because MSBuild cannot determine which outputs need to be rebuilt if some of the inputs have changed.

Tasks in which you can identify a direct mapping between the outputs and inputs, such as the GenerateResource.task, are most suitable for incremental builds, unlike tasks such as Csc and Vbc, which produce one output assembly from a number of inputs.

Example

In the following code example, the project uses transforms to create a one-to-one mapping between inputs and outputs in the GenerateResource task. Also, the Output element is set to automatically use the outputs from the GenerateResource task as the inputs for the Csc task.

This project file contains both the Resources and Build targets. The GenerateResource and Csc tasks are placed in the Resources and Build targets respectively so that each target can be built incrementally. By using the Output element, the outputs of the GenerateResource task are placed in the Resources item collection, and they are then used as inputs for the Csc task. Using the Output element in this way, you can automatically use the outputs from one task as the inputs for another task; you do not have to list the individual items or item collections in each task.

Note

Although the Resources target can build incrementally, all the outputs from that target are always required as inputs for the Build target. MSBuild automatically provides all the outputs from one target as inputs for another target when you use the Output element. This method can be used with other tasks; it is not only for the GenerateResource and Csc tasks.

<Project DefaultTargets="Compile"
    xmlns="https://schemas.microsoft.com/developer/msbuild/2003" >

    <ItemGroup>
        <RESXFile Include="*.resx"/>
        <TXTFile Include="*.txt"/>
        <CSFile Include="*.cs"/>
    </ItemGroup>

    <Target Name = "Resources"
        Inputs="@(RESXFile); @(TXTFile)"
        Outputs="@(RESXFile->'%(Filename).resources');
        @(TXTFile->'%(Filename).resources')">

        <GenerateResource
            Sources = "@(RESXFile); @(TXTFile)">
            <Output TaskParameter = "OutputResources"
                ItemName = "Resources"/>
        </GenerateResource>
    </Target>

    <Target Name = "Build" DependsOnTargets = "Resources"
        Inputs="@(CSFiles); @(Resources)"
        Outputs="$(MSBuildProjectName).exe">

        <Csc
            Sources = "@(CSFile)"
            Resources = "@(Resources)"
            OutputAssembly = "$(MSBuildProjectName).exe"/>
    </Target>
</Project>

See Also

Reference

Target Element (MSBuild)
GenerateResource Task
Csc Task
Vbc Task

Concepts

MSBuild Transforms