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