9
votes

In our project files we are using StyleCop and are running it during the build process. We've modified our project files to include the StyleCop targets like so:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
<Import Project="..\..\Tools\Microsoft\StyleCop\v4.3\Microsoft.StyleCop.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
     Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

The question is why does this work? Who is calling the StyleCop target defined in the Microsoft.StyleCop.targets file?

As far as I can tell, the only target being run when you start the build, is the "Build" target. I can't find any references to the "StyleCop" target anywhere outside the Microsoft.StyleCop.targets file. So again, why is it being called?

The reason I want to know is because it would be cool if we could do something similar for our own custom tasks. So instead of editing all of our 78 csproj files, we could just import our own general target like:

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
<Import Project="Common.targets" />

And then just import StyleCop in that file instead, along with all our other tasks that need to be done on a per project basis.

Please help me understand.

1

1 Answers

9
votes

Eureka!

The secret sauce is the following lines in the StyleCop targets file:

<PropertyGroup>
  <BuildDependsOn>$(BuildDependsOn);StyleCop</BuildDependsOn>
  <RebuildDependsOn>StyleCopForceFullAnalysis;$(RebuildDependsOn)</RebuildDependsOn>
</PropertyGroup>

The "Build" target in Microsoft.Common.targets is declared like so:

<Target Name="Build"
        Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
        DependsOnTargets="$(BuildDependsOn)"
        Outputs="$(TargetPath)" />

This means that any target listed in the "BuildDependsOn" property will get called during the build. Isn't that nice? :)