Dissecting Microsoft.TeamFoundation.Build.targets

If you have ever tried to customize a Build Type in TeamBuild, you have probably come across or heard about this file - Microsoft.TeamFoundation.Build.targets. What is this file?

 

This is the file that defines the entire build process. All the steps needed to orchestrate a plain vanilla out of the box build go into this file. Think of this as the Conductor for the concert that is TeamBuild (Yes, it is one of my faults, I get melodramatic at times). TFSBuild.proj(the build type file) is like a wrapper to this file and is the place where you can customize each build type.

 

If you look at TFSBuild.proj you will see this line:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\TeamBuild\Microsoft.TeamFoundation.Build.targets" />

 

Anything that comes after this line just overrides the targets and properties defined in Microsoft.TeamFoundation.Build.targets. Having said that the first question that comes to mind (especially if you’re a 3GL programmer) is where does it all start? Where is the entry point?

 

Open up Microsoft.TeamFoundation.Build.targets and scroll down till you find this:

  <PropertyGroup>

    <EndToEndIterationDependsOn>

      BeforeEndToEndIteration;

      BuildNumberOverrideTarget;

      InitializeEndToEndIteration;

      Clean;

      TeamBuild;

      DropBuild;

      AfterEndToEndIteration;

    </EndToEndIterationDependsOn>

  </PropertyGroup>

  <!-- Entry point: this target is invoked on the build machine by the build agent -->

  <Target Name="EndToEndIteration"

          Condition=" '$(IsDesktopBuild)'!='true' "

          DependsOnTargets="$(EndToEndIterationDependsOn)" />

 

The build agent just invokes the target EndToEndIteration which will execute only after the targets it “depends on” are executed. These targets in turn depend on others(the rabbit hole runs deep here). This defines the execution order for the build steps.

 

Many of these targets are just empty targets which can be overridden. For example BuildNumberOverrideTarget is one such empty target. If you want to have a different build numbering scheme than the one that is shipped, you can override this target. Manish describes this in his blog.

 

This file also defines many properties that can be overridden to customize the build process. This rather self-explanatory Property is an example:

    <!-- Set this property to true to skip Get task -->

    <SkipGet Condition=" '$(SkipGet)'=='' " >false</SkipGet>

 

A word of warning here - do not modify Microsoft.TeamFoundation.Build.targets as this will reflect your changes across all your current and future Team projects and all build types. TFSBuild.proj is the place for customization.

 

How do Desktop Builds work then?

 

See this little parameter called DefaultTargets="DesktopBuild" in the Project tag in TFSBuild.proj?

 

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

Since a desktop build is initiated by calling MSBuild with the TFSBuild.proj, MSBuild will execute the DefaultTarget.

 

This is the DesktopBuild target in Microsoft.TeamFoundation.Build.targets

  <PropertyGroup>

    <DesktopBuildDependsOn>

      Compile;

      Test;

    </DesktopBuildDependsOn>

  </PropertyGroup>

  <Target Name="DesktopBuild"

          Condition=" '$(IsDesktopBuild)'=='true' "

          DependsOnTargets="$(DesktopBuildDependsOn)" />

Now just follow the white rabbit –sorry- the target dependencies to uncover the entire process.