Home | History | Annotate | Line # | Download | only in diag-build
      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