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