| #!/bin/bash | 
 |  | 
 | # diag-build: a tool showing enabled warnings in a project. | 
 | # | 
 | # diag-build acts as a wrapper for 'diagtool show-enabled', in the same way | 
 | # that scan-build acts as a wrapper for the static analyzer. The common case is | 
 | # simple: use 'diag-build make' or 'diag-build xcodebuild' to list the warnings | 
 | # enabled for the first compilation command we see. Other build systems require | 
 | # you to manually specify "dry-run" and "use $CC and $CXX"; if there is a build | 
 | # system you are interested in, please add it to the switch statement. | 
 |  | 
 | print_usage () { | 
 |     echo 'Usage: diag-build.sh [-v] xcodebuild [flags]' | 
 |     echo '       diag-build.sh [-v] make [flags]' | 
 |     echo '       diag-build.sh [-v] <other build command>' | 
 |     echo | 
 |     echo 'diagtool must be in your PATH' | 
 |     echo 'If using an alternate build command, you must ensure that' | 
 |     echo 'the compiler used matches the CC environment variable.' | 
 | } | 
 |  | 
 | # Mac OS X's BSD sed uses -E for extended regular expressions, | 
 | # but GNU sed uses -r. Find out which one this system accepts. | 
 | EXTENDED_SED_FLAG='-E' | 
 | echo -n | sed $EXTENDED_SED_FLAG 's/a/b/' 2>/dev/null || EXTENDED_SED_FLAG='-r' | 
 |  | 
 | if [[ "$1" == "-v" ]]; then | 
 |     verbose=$1 | 
 |     shift | 
 | fi | 
 |  | 
 | guessing_cc=0 | 
 |  | 
 | if [[ -z "$CC" ]]; then | 
 |     guessing_cc=1 | 
 |     if [[ -x $(dirname $0)/clang ]]; then | 
 | 	CC=$(dirname $0)/clang | 
 |     elif [[ ! -z $(which clang) ]]; then | 
 | 	CC=$(which clang) | 
 |     else | 
 | 	echo -n 'Error: could not find an appropriate compiler' | 
 | 	echo ' to generate build commands.' 1>&2 | 
 | 	echo 'Use the CC environment variable to set one explicitly.' 1>&2 | 
 | 	exit 1 | 
 |     fi | 
 | fi | 
 |  | 
 | if [[ -z "$CXX" ]]; then | 
 |     if [[ -x $(dirname $0)/clang++ ]]; then | 
 | 	CXX=$(dirname $0)/clang++ | 
 |     elif [[ ! -z $(which clang++) ]]; then | 
 | 	CXX=$(which clang++) | 
 |     else | 
 | 	CXX=$CC | 
 |     fi | 
 | fi | 
 |  | 
 | diagtool=$(which diagtool) | 
 | if [[ -z "$diagtool" ]]; then | 
 |     if [[ -x $(dirname $0)/diagtool ]]; then | 
 | 	diagtool=$(dirname $0)/diagtool | 
 |     else | 
 | 	echo 'Error: could not find diagtool.' 1>&2 | 
 | 	exit 1 | 
 |     fi | 
 | fi | 
 |  | 
 |  | 
 | tool=$1 | 
 | shift | 
 |  | 
 | if [[ -z "$tool" ]]; then | 
 |     print_usage | 
 |     exit 1 | 
 | elif [[ "$tool" == "xcodebuild" ]]; then | 
 |     dry_run='-dry-run' | 
 |     set_compiler="CC='$CC' CXX='$CXX'" | 
 | elif [[ "$tool" == "make" ]]; then | 
 |     dry_run='-n' | 
 |     set_compiler="CC='$CC' CXX='$CXX'" | 
 | else | 
 |     echo "Warning: unknown build system '$tool'" 1>&2 | 
 |     if [[ $guessing_cc -eq 1 ]]; then | 
 | 	# FIXME: We really only need $CC /or/ $CXX | 
 | 	echo 'Error: $CC must be set for other build systems' 1>&2 | 
 | 	exit 1 | 
 |     fi | 
 | fi | 
 |  | 
 | escape () { | 
 |     echo $@ | sed 's:[]:\\|/.+*?^$(){}[]:\\&:g' | 
 | } | 
 |  | 
 | escCC=$(escape $CC) | 
 | escCXX=$(escape $CXX) | 
 | command=$( | 
 |     eval $tool $dry_run $set_compiler $@ 2>/dev/null | | 
 |     # Remove "if" early on so we can find the right command line. | 
 |     sed $EXTENDED_SED_FLAG "s:^[[:blank:]]*if[[:blank:]]{1,}::g" | | 
 |     # Combine lines with trailing backslashes | 
 |     sed -e :a -e '/\\$/N; s/\\\n//; ta' | | 
 |     grep -E "^[[:blank:]]*($escCC|$escCXX)" | | 
 |     head -n1 | | 
 |     sed $EXTENDED_SED_FLAG "s:($escCC|$escCXX):${diagtool//:/\\:} show-enabled:g" | 
 | ) | 
 |  | 
 | if [[ -z "$command" ]]; then | 
 |     echo 'Error: could not find any build commands.' 1>&2 | 
 |     if [[ "$tool" != "xcodebuild" ]]; then | 
 | 	# xcodebuild always echoes the compile commands on their own line, | 
 | 	# but other tools give no such guarantees. | 
 | 	echo -n 'This may occur if your build system embeds the call to ' 2>&1 | 
 | 	echo -n 'the compiler in a larger expression. ' 2>&1 | 
 |     fi | 
 |     exit 2 | 
 | fi | 
 |  | 
 | # Chop off trailing '&&', '||', and ';' | 
 | command=${command%%&&*} | 
 | command=${command%%||*} | 
 | command=${command%%;*} | 
 |  | 
 | [[ -n "$verbose" ]] && echo $command | 
 | eval $command |