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