1#!/bin/bash 2 3# diag-build: a tool showing enabled warnings in a project. 4# 5# diag-build acts as a wrapper for 'diagtool show-enabled', in the same way 6# that scan-build acts as a wrapper for the static analyzer. The common case is 7# simple: use 'diag-build make' or 'diag-build xcodebuild' to list the warnings 8# enabled for the first compilation command we see. Other build systems require 9# you to manually specify "dry-run" and "use $CC and $CXX"; if there is a build 10# system you are interested in, please add it to the switch statement. 11 12print_usage () { 13 echo 'Usage: diag-build.sh [-v] xcodebuild [flags]' 14 echo ' diag-build.sh [-v] make [flags]' 15 echo ' diag-build.sh [-v] <other build command>' 16 echo 17 echo 'diagtool must be in your PATH' 18 echo 'If using an alternate build command, you must ensure that' 19 echo 'the compiler used matches the CC environment variable.' 20} 21 22# Mac OS X's BSD sed uses -E for extended regular expressions, 23# but GNU sed uses -r. Find out which one this system accepts. 24EXTENDED_SED_FLAG='-E' 25echo -n | sed $EXTENDED_SED_FLAG 's/a/b/' 2>/dev/null || EXTENDED_SED_FLAG='-r' 26 27if [[ "$1" == "-v" ]]; then 28 verbose=$1 29 shift 30fi 31 32guessing_cc=0 33 34if [[ -z "$CC" ]]; then 35 guessing_cc=1 36 if [[ -x $(dirname $0)/clang ]]; then 37 CC=$(dirname $0)/clang 38 elif [[ ! -z $(which clang) ]]; then 39 CC=$(which clang) 40 else 41 echo -n 'Error: could not find an appropriate compiler' 42 echo ' to generate build commands.' 1>&2 43 echo 'Use the CC environment variable to set one explicitly.' 1>&2 44 exit 1 45 fi 46fi 47 48if [[ -z "$CXX" ]]; then 49 if [[ -x $(dirname $0)/clang++ ]]; then 50 CXX=$(dirname $0)/clang++ 51 elif [[ ! -z $(which clang++) ]]; then 52 CXX=$(which clang++) 53 else 54 CXX=$CC 55 fi 56fi 57 58diagtool=$(which diagtool) 59if [[ -z "$diagtool" ]]; then 60 if [[ -x $(dirname $0)/diagtool ]]; then 61 diagtool=$(dirname $0)/diagtool 62 else 63 echo 'Error: could not find diagtool.' 1>&2 64 exit 1 65 fi 66fi 67 68 69tool=$1 70shift 71 72if [[ -z "$tool" ]]; then 73 print_usage 74 exit 1 75elif [[ "$tool" == "xcodebuild" ]]; then 76 dry_run='-dry-run' 77 set_compiler="CC='$CC' CXX='$CXX'" 78elif [[ "$tool" == "make" ]]; then 79 dry_run='-n' 80 set_compiler="CC='$CC' CXX='$CXX'" 81else 82 echo "Warning: unknown build system '$tool'" 1>&2 83 if [[ $guessing_cc -eq 1 ]]; then 84 # FIXME: We really only need $CC /or/ $CXX 85 echo 'Error: $CC must be set for other build systems' 1>&2 86 exit 1 87 fi 88fi 89 90escape () { 91 echo $@ | sed 's:[]:\\|/.+*?^$(){}[]:\\&:g' 92} 93 94escCC=$(escape $CC) 95escCXX=$(escape $CXX) 96command=$( 97 eval $tool $dry_run $set_compiler $@ 2>/dev/null | 98 # Remove "if" early on so we can find the right command line. 99 sed $EXTENDED_SED_FLAG "s:^[[:blank:]]*if[[:blank:]]{1,}::g" | 100 # Combine lines with trailing backslashes 101 sed -e :a -e '/\\$/N; s/\\\n//; ta' | 102 grep -E "^[[:blank:]]*($escCC|$escCXX)" | 103 head -n1 | 104 sed $EXTENDED_SED_FLAG "s:($escCC|$escCXX):${diagtool//:/\\:} show-enabled:g" 105) 106 107if [[ -z "$command" ]]; then 108 echo 'Error: could not find any build commands.' 1>&2 109 if [[ "$tool" != "xcodebuild" ]]; then 110 # xcodebuild always echoes the compile commands on their own line, 111 # but other tools give no such guarantees. 112 echo -n 'This may occur if your build system embeds the call to ' 2>&1 113 echo -n 'the compiler in a larger expression. ' 2>&1 114 fi 115 exit 2 116fi 117 118# Chop off trailing '&&', '||', and ';' 119command=${command%%&&*} 120command=${command%%||*} 121command=${command%%;*} 122 123[[ -n "$verbose" ]] && echo $command 124eval $command 125