Clang Project

clang_source_code/tools/diag-build/diag-build.sh
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