Welcome to EMC Consulting Blogs Sign in | Join | Help

John Rayner's Blog (2006-2010)

Brain.Extract<IBloggable>( Where.Author.Is( "John.Rayner" ) );

Getting FxCop to break the build

EDIT: I became a SharpFellow and so this blog post has moved  

Recently I wrote a long post on our continuous build setup and what we had to do to get it all working.  However, switching on FxCop wasn't quite as simple as I thought it was going to be.

The Problem
You might recall that we are using the FxCop task from the MSBuild Community Tasks project at http://msbuildtasks.tigris.org/ and our build script looked like this:

 <FxCop 
    TargetAssemblies="@(FxcopTargets)"
    RuleLibraries="@(FxCopRuleAssemblies)" 
    AnalysisReportFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    DependencyDirectories="$(MSBuildCommunityTasksPath);C:\Program Files\Extreme Optimization\Statistics Library for .NET\bin;D:\Projects\MyProject\Build\Tools\log4net-1.2.10\bin\net\2.0\debug;C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0"
    FailOnError="False"
    ApplyOutXsl="False"
    OutputXslFileName="C:\Program Files\Microsoft FxCop 1.35\Xml\FxCopReport.xsl"
    Verbose="False"
    includeSummaryReport="True"
    ExcludeRules="Microsoft.Design#CA2210;Microsoft.Globalization#CA1303"
   
/>

Now we set FailOnError="True" and thought that would be enough.  Turns out it isn't.  For those who interested, the reasons for this are as follows:

  • Setting FailOnError="True" ensures that the return value of the external FxCop process is returned to MSBuild as a task status (you can see this in the source code for the FxCop task)
  • The FxCop task shells out to FxCopCmd.exe
  • The return values for FxCopCmd.exe are used to indicate a catastrophic failure in the analysis process, not rule violations

In other words, this setting simply ensures that if the code analysis cannot be carried out, then the build will fail.  This is useful, but not what I wanted.

The Solution
All the violations of FxCop rules are written out to an XML file by the above script.  So we have to load that XML file and parse out any violations which we think are important.  Fortunately the MSBuild Community Tasks project include an XmlRead task, which allows you to execute some XPath against a XML document and get the results into an MSBuild property.  Our build script now includes the following:

</PropertyGroup>
    <
FxCopCriticalErrors>0</FxCopCriticalErrors>
    <
FxCopErrors>0</FxCopErrors>
    <
FxCopCriticalWarnings>0</FxCopCriticalWarnings>
</
PropertyGroup>
<XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='CriticalError']))">
        <
Output TaskParameter="Value" PropertyName="FxCopCriticalErrors" />
</
XmlRead>
<
XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='Error']))">
        <
Output TaskParameter="Value" PropertyName="FxCopErrors" />
</
XmlRead>
<
XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='CriticalWarning']))">
        <
Output TaskParameter="Value" PropertyName="FxCopCriticalWarnings" />
</
XmlRead>
<
Error Text="FxCop encountered $(Count) material rule violations"
    Condition="$(FxCopCriticalErrors) &gt; 0 or $(FxCopErrors) &gt; 0 or $(FxCopCriticalWarnings) &gt; 0" />

PropertyGroup>
    <
FxCopCriticalErrors>0</FxCopCriticalErrors>
    <
FxCopErrors>0</FxCopErrors>
    <
FxCopCriticalWarnings>0</FxCopCriticalWarnings>
</
PropertyGroup>
<XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='CriticalError']))">
        <
Output TaskParameter="Value" PropertyName="FxCopCriticalErrors" />
</
XmlRead>
<
XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='Error']))">
        <
Output TaskParameter="Value" PropertyName="FxCopErrors" />
</
XmlRead>
<
XmlRead ContinueOnError="True"
    XmlFileName="D:\Projects\MyProject\Build\SmokeTest\fxcop.xml"
    XPath="string(count(//Issue[@Level='CriticalWarning']))">
        <
Output TaskParameter="Value" PropertyName="FxCopCriticalWarnings" />
</
XmlRead>
<
Error Text="FxCop encountered $(Count) material rule violations"
    Condition="$(FxCopCriticalErrors) &gt; 0 or $(FxCopErrors) &gt; 0 or $(FxCopCriticalWarnings) &gt; 0" />

Not only does this work, but it also gives you a lot of control over what you consider important.  For instance, we break the build for Critical Warnings as well as Errors and Critical Errors.  You could also use this script to enforce limits on the types of violations, so you may want to break the build if there are more than 30 warnings.

You may be surprised by the ContinueOnError="True" but this is to cope with the fact the FxCop doesn't produce any XML output if there are no violations.  In this (happy) case, the default property values of 0 will be used as the XmlRead task will not set the property values.

Comments

 

howard.vanrooijen said:

Nice! You can also use the inbuilt FxCop task in the Microsoft SDC Build Tools (see http://blogs.conchango.com/howardvanrooijen/archive/2006/03/01/3016.aspx for a list of all the supported tasks).

You can then then create an <Output /> which maps to the TaskParameter to "TotalViolations" and then perform a <LogicalComparison/> to determine if your number of FxCop errors exceeds 0 - or your specified limit then raise an <Error/> if the <LogicalComparison/> returns true...

October 5, 2006 14:24
 

imeshev said:

You might also want to check our Parabuild - it allows you both to use string patterns and command result codes to detect build breakage: http://www.viewtier.com/products/parabuild/index.htm

October 5, 2006 19:27
 

fxcop fails msbuild said:

June 4, 2008 13:49
 

Adding FxCop to a “FAKE” build script » Rash thoughts about .NET, C#, F# and Dynamics NAV. said:

April 3, 2009 09:16
 

Making Sure FxCop Warnings and Errors Break the Build | #2782 - Agile software development, patterns and practices for building Microsoft .NET applications. said:

June 18, 2009 17:38
Anonymous comments are disabled
Powered by Community Server (Personal Edition), by Telligent Systems