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

2

12

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.

Scheck answered 17/2, 2011 at 19:10 Comment(2)
This is great. Wish it were easier, but it works! Trying to get it to work with things in the Pods folder, which it currently doesn't.Latticed
Hmmm, this looked to be working perfectly (it does with Apps and Frameworks) but for some reason Static Library targets don't output the link file despite LD_GENERATE_MAP_FILE=YES and so the script doesn't run. Any ideas why?Finned
I
2

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.

Irvingirwin answered 18/2, 2011 at 16:34 Comment(2)
Thanks Jim. An additional build step for the target that examines the analysis results may be the way to go. I'll look into this.Scheck
I came up with a script for a build step that works pretty well. See the solution above. Thanks again Jim.Scheck
B
-2

Xcode has a "Treat warnings as errors" checkbox. If you can't find it, which has been said for some iPhone projects, just add "-Werror" to your WARNING_CFLAGS in the Build Settings for your target(s) in question.

Belter answered 17/2, 2011 at 19:16 Comment(3)
We've got -Werror enabled (see above) and it's been working fine for turning compiler warnings into errors. It doesn't appear to turn a clang --analyze warning into an error though.Scheck
Ah, I overlooked that. My mistake. I'll see if I can get you something more pertinent.Belter
Thanks for looking into this Jeremy.Scheck

© 2022 - 2024 — McMap. All rights reserved.