Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to treat warnings from clang static code analysis as errors in Xcode 3?

Question

The RUN_CLANG_STATIC_ANALYZER ("Run Static Analyzer") project setting has found important issues in our project. We have addressed them and we want to prevent future issues from creeping in.

We're trying to get clang analysis warnings to be treated as errors to break our build. So far no success despite having -Werror ("Treat Warnings as Errors") enabled.

Example of Problem

The following analysis call generated within Xcode:

/Developer/usr/bin/clang -x objective-c [...] --analyze [...]/TroubledCode.m -o [...]/TroubledTarget.build/StaticAnalyzer/normal/i386/TroubledCode.plist

produces a static code analysis warning:

[...]/TroubledCode.m:38:34: warning: Potential leak of an object allocated on line 38 and stored into 'leakingManager'
    Manager *leakingManager = [[Manager alloc] init];
                              ^
1 warning generated.

but Xcode reports "Build Succeeded ... 1 analyzer result". The solution we're looking for would make the example above generate a "Build Failed".


Solution

I took Jim's advice and created a build script.

To avoid false alarms, I went through the trouble of making sure it ignores extraneous analysis residue. This solution should work when building from the Xcode IDE and when building your project using xcodebuild.

To turn Xcode 3 analysis warnings into build errors:

  • Double click the project or target in question.
  • Under the Build tab, check the box under Settings > Linking > Write Link Map File

That setting is also known as LD_GENERATE_MAP_FILE.

  • Under "Groups & Files" > "Targets", click the disclosure triangle of the target you'd like to add this feature to.
  • Right-click the "Link Binary With Libraries" phase.
  • select Add > New Build Phase > New Run Script Build Phase
  • optional: Rename the "Run Script" phase you just added to "Treat Clang Warnings as Errors".
  • Double-click the new script phase if it's not already open.

Copy the content below and paste it into the "Script" section.

error_count=0

##

function verify_clang_analysis_at_path()
{
  local analysis_path=$1
  local plist_tool=/usr/libexec/PlistBuddy
  local diagnostics=$($plist_tool -c "print diagnostics" $analysis_path)

  if [[ $diagnostics != $'Array {\n}' ]]
  then
    ((error_count++))
  fi
}

function verify_clang_analysis_for_object_file()
{
  local object_file=$1
  local analysis_directory=$TARGET_TEMP_DIR/StaticAnalyzer/$CURRENT_VARIANT/$CURRENT_ARCH
  local analysis_path=$analysis_directory/${object_file%.*}.plist

  # if this object file corresponds to a source file that clang analyzed...
  if [ -e $analysis_path ]
  then
    verify_clang_analysis_at_path $analysis_path
  fi
}

##

object_directory=$OBJECT_FILE_DIR-$CURRENT_VARIANT/$CURRENT_ARCH
object_path_pattern=${object_directory}'/\(.\)\+\.o$'

index_pattern='\[[[:space:]0-9]*\][[:space:]]'

object_paths=$( 
  grep $object_path_pattern $LD_MAP_FILE_PATH | sed s/$index_pattern//
)

##

for object_path in $object_paths 
do
  object_file=${object_path##*/}
  verify_clang_analysis_for_object_file $object_file
done

if [ $error_count -gt 0 ]
then
   echo "Clang static code analysis failed for" $error_count "source file(s)."
fi

exit $error_count

Update

Mike Vosseller has an upgraded version of this script for Xcode 5.

like image 768
otto Avatar asked Feb 17 '11 19:02

otto


1 Answers

We've been planning on having a separate build step to run the analyzer and check the results. We'll fail the build on the build server that way. That won't help you locally, though.

like image 141
JimDusseau Avatar answered Nov 11 '22 20:11

JimDusseau