How to: Build Incrementally
This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, use the version selector at the top left. We recommend upgrading to Visual Studio 2019. Download it here
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 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
Outputsattributes of the
Targetelement. 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 list 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.
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 LC Task, are most suitable for incremental builds, unlike tasks such as
Csc and Vbc, which produce one output assembly from a number of inputs.
The following example uses a project that builds Help files for a hypothetical Help system. The project works by converting source .txt files into intermediate .content files, which then are combined with XML metadata files to produce the final .help file used by the Help system. The project uses the following hypothetical tasks:
GenerateContentFiles: Converts .txt files into .content files.
BuildHelp: Combines .content files and XML metadata files to build the final .help file.
The project uses transforms to create a one-to-one mapping between inputs and outputs in the
GenerateContentFilestask. For more information, see Transforms. Also, the
Outputelement is set to automatically use the outputs from the
GenerateContentFilestask as the inputs for the
This project file contains both the
BuildHelptasks are placed in the
Buildtargets respectively so that each target can be built incrementally. By using the
Outputelement, the outputs of the
GenerateContentFilestask are placed in the
ContentFileitem list, where they can be used as inputs for the
BuildHelptask. Using the
Outputelement in this way automatically provides the outputs from one task as the inputs for another task so that you do not have to list the individual items or item lists manually in each task.
GenerateContentFiles target can build incrementally, all outputs from that target always are required as inputs for the
BuildHelp target. MSBuild automatically provides all the outputs from one target as inputs for another target when you use the
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" > <ItemGroup> <TXTFile Include="*.txt"/> <XMLFile Include="\metadata\*.xml"/> </ItemGroup> <Target Name = "Convert" Inputs="@(TXTFile)" Outputs="@(TXTFile->'%(Filename).content')"> <GenerateContentFiles Sources = "@(TXTFile)"> <Output TaskParameter = "OutputContentFiles" ItemName = "ContentFiles"/> </GenerateContentFiles> </Target> <Target Name = "Build" DependsOnTargets = "Convert" Inputs="@(ContentFiles);@(XMLFiles)" Outputs="$(MSBuildProjectName).help"> <BuildHelp ContentFiles = "@(ContentFiles)" MetadataFiles = "@(XMLFile)" OutputFileName = "$(MSBuildProjectName).help"/> </Target> </Project>