1#!/bin/sh
2
3#  Multi-build script for testing compilation of all maintained
4#  configs of GDB.
5
6#  Copyright 2002, 2003 Free Software Foundation, Inc.
7
8#  Contributed by Richard Earnshaw  (rearnsha@arm.com)
9
10#  This program is free software; you can redistribute it and/or modify
11#  it under the terms of the GNU General Public License as published by
12#  the Free Software Foundation; either version 2 of the License, or
13#  (at your option) any later version.
14
15#  This program is distributed in the hope that it will be useful,
16#  but WITHOUT ANY WARRANTY; without even the implied warranty of
17#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18#  GNU General Public License for more details.
19
20#  You should have received a copy of the GNU General Public License
21#  along with this program; if not, write to the Free Software
22#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
24usage()
25{
26    cat <<EOF
27Usage: gdb_mbuild.sh [ <options> ... ] <srcdir> <builddir>
28 Options:
29   -j <makejobs>  Run <makejobs> in parallel.  Passed to make.
30	          On a single cpu machine, 2 is recommended.
31   -k             Keep going.  Do not stop after the first build fails.
32   --keep         Keep builds.  Do not remove each build when finished.
33   -e <regexp>    Regular expression for selecting the targets to build.
34   -f             Force rebuild.  Even rebuild previously built directories.
35   -v             Be more (and more, and more) verbose.
36 Arguments:
37   <srcdir>       Source code directory.
38   <builddir>     Build directory.
39 Environment variables examined (with default if not defined):
40   MAKE (make)"
41EOF
42    exit 1;
43cat <<NOTYET
44  -b <maxbuilds> Run <maxbuild> builds in parallel.
45		 On a single cpu machine, 1 is recommended.
46NOTYET
47}
48
49### COMMAND LINE OPTIONS
50
51makejobs=
52maxbuilds=1
53keepgoing=
54force=false
55targexp=""
56verbose=0
57keep=false
58while test $# -gt 0
59do
60    case "$1" in
61    -j )
62	# Number of parallel make jobs.
63	shift
64	test $# -ge 1 || usage
65	makejobs="-j $1"
66	;;
67    -b | -c )
68	# Number of builds to fire off in parallel.
69	shift
70	test $# -ge 1 || usage
71	maxbuilds=$1
72	;;
73    -k )
74	# Should we soldier on after the first build fails?
75	keepgoing=-k
76	;;
77    --keep )
78        keep=true
79	;;
80    -e )
81	# A regular expression for selecting targets
82	shift
83	test $# -ge 1 || usage
84	targexp="${targexp} -e ${1}"
85	;;
86    -f )
87	# Force a rebuild
88	force=true ;
89	;;
90    -v )
91	# Be more, and more, and more, verbose
92	verbose=`expr ${verbose} + 1`
93	;;
94    -* ) usage ;;
95    *) break ;;
96    esac
97    shift
98done
99
100
101### COMMAND LINE PARAMETERS
102
103if test $# -ne 2
104then
105    usage
106fi
107
108# Convert these to absolute directory paths.
109
110# Where the sources live
111srcdir=`cd $1 && /bin/pwd` || exit 1
112
113# Where the builds occur
114builddir=`cd $2 && /bin/pwd` || exit 1
115
116### ENVIRONMENT PARAMETERS
117
118# Version of make to use
119make=${MAKE:-make}
120MAKE=${make}
121export MAKE
122
123
124# Where to look for the list of targets to test
125maintainers=${srcdir}/gdb/MAINTAINERS
126if [ ! -r ${maintainers} ]
127then
128    echo Maintainers file ${maintainers} not found
129    exit 1
130fi
131
132# Get the list of targets and the build options
133alltarg=`cat ${maintainers} | tr -s '[\t]' '[ ]' | sed -n '
134/^[ ]*[-a-z0-9\.]*[ ]*[(]*--target=.*/ !d
135s/^.*--target=//
136s/).*$//
137h
138:loop
139  g
140  /^[^ ]*,/ !b end
141  s/,[^ ]*//
142  p
143  g
144  s/^[^,]*,//
145  h
146b loop
147:end
148p
149' | if test "${targexp}" = ""
150then
151    grep -v -e broken -e OBSOLETE
152else
153    grep ${targexp}
154fi`
155
156
157# Usage: fail <message> <test-that-should-succeed>.  Should the build
158# fail?  If the test is true, and we don't want to keep going, print
159# the message and shoot everything in sight and abort the build.
160
161fail ()
162{
163    msg="$1" ; shift
164    if test "$@"
165    then
166	echo "${target}: ${msg}"
167	if test "${keepgoing}" != ""
168	then
169	    #exit 1
170	    continue
171	else
172	    kill $$
173	    exit 1
174	fi
175    fi
176}
177
178
179# Usage: log <level> <logfile>.  Write standard input to <logfile> and
180# stdout (if verbose >= level).
181
182log ()
183{
184    if test ${verbose} -ge $1
185    then
186	tee $2
187    else
188	cat > $2
189    fi
190}
191
192
193
194# Warn the user of what is comming, print the list of targets
195
196echo "$alltarg"
197echo ""
198
199
200# For each target, configure, build and test it.
201
202echo "$alltarg" | while read target gdbopts simopts
203do
204
205    trap "exit 1"  1 2 15
206    dir=${builddir}/${target}
207
208    # Should a scratch rebuild be forced, for perhaphs the entire
209    # build be skipped?
210
211    if ${force}
212    then
213	echo forcing ${target} ...
214	rm -rf ${dir}
215    elif test -f ${dir}
216    then
217	echo "${target}"
218	continue
219    else
220	echo ${target} ...
221    fi
222
223    # Did the previous configure attempt fail?  If it did
224    # restart from scratch.
225
226    if test -d ${dir} -a ! -r ${dir}/Makefile
227    then
228	echo ... removing partially configured ${target}
229	rm -rf ${dir}
230	if test -d ${dir}
231	then
232	    echo "${target}: unable to remove directory ${dir}"
233	    exit 1
234	fi
235    fi
236
237    # From now on, we're in this target's build directory
238
239    mkdir -p ${dir}
240    cd ${dir} || exit 1
241
242    # Configure, if not already.  Should this go back to being
243    # separate and done in parallel?
244
245    if test ! -r Makefile
246    then
247	# Default SIMOPTS to GDBOPTS.
248	test -z "${simopts}" && simopts="${gdbopts}"
249	# The config options
250	__target="--target=${target}"
251	__enable_gdb_build_warnings=`test -z "${gdbopts}" \
252	    || echo "--enable-gdb-build-warnings=${gdbopts}"`
253	__enable_sim_build_warnings=`test -z "${simopts}" \
254	    || echo "--enable-sim-build-warnings=${simopts}"`
255	__configure="${srcdir}/configure \
256	    ${__target} \
257	    ${__enable_gdb_build_warnings} \
258	    ${__enable_sim_build_warnings}"
259	echo ... ${__configure}
260	trap "echo Removing partially configured ${dir} directory ...; rm -rf ${dir}; exit 1" 1 2 15
261	${__configure} 2>&1 | log 2 Config.log
262	trap "exit 1"  1 2 15
263    fi
264    fail "configure failed" ! -r Makefile
265
266    # Build, if not built.
267
268    if test ! -x gdb/gdb -a ! -x gdb/gdb.exe
269    then
270	# Iff the build fails remove the final build target so that
271	# the follow-on code knows things failed.  Stops the follow-on
272	# code thinking that a failed rebuild succedded (executable
273	# left around from previous build).
274	echo ... ${make} ${keepgoing} ${makejobs} ${target}
275	( ${make} ${keepgoing} ${makejobs} all-gdb || rm -f gdb/gdb gdb/gdb.exe
276	) 2>&1 | log 1 Build.log
277    fi
278    fail "compile failed" ! -x gdb/gdb -a ! -x gdb/gdb.exe
279
280    # Check that the built GDB can at least print it's architecture.
281
282    echo ... run ${target}
283    rm -f core gdb.core ${dir}/gdb/x
284    cat <<EOF > x
285maint print architecture
286quit
287EOF
288    ./gdb/gdb -batch -nx -x x 2>&1 | log 1 Gdb.log
289    fail "gdb dumped core" -r core -o -r gdb.core
290    fail "gdb printed no output" ! -s Gdb.log
291    grep -e internal-error Gdb.log && fail "gdb panic" 1
292
293    echo ... cleanup ${target}
294
295    # Create a sed script that cleans up the output from GDB.
296    rm -f mbuild.sed
297    touch mbuild.sed || exit 1
298    # Rules to replace <0xNNNN> with the corresponding function's
299    # name.
300    sed -n -e '/<0x0*>/d' -e 's/^.*<0x\([0-9a-f]*\)>.*$/0x\1/p' Gdb.log \
301    | sort -u \
302    | while read addr
303    do
304	func="`addr2line -f -e ./gdb/gdb -s ${addr} | sed -n -e 1p`"
305	test ${verbose} -gt 0 && echo "${addr} ${func}" 1>&2
306	echo "s/<${addr}>/<${func}>/g"
307    done >> mbuild.sed
308    # Rules to strip the leading paths off of file names.
309    echo 's/"\/.*\/gdb\//"gdb\//g' >> mbuild.sed
310    # Run the script
311    sed -f mbuild.sed Gdb.log > Mbuild.log
312
313    # Replace the build directory with a file as semaphore that stops
314    # a rebuild. (should the logs be saved?)
315
316    cd ${builddir}
317
318    if ${keep}
319    then
320	:
321    else
322	rm -f ${target}.tmp
323	mv ${target}/Mbuild.log ${target}.tmp
324	rm -rf ${target}
325	mv ${target}.tmp ${target}
326    fi
327
328    # Success!
329    echo ... ${target} built
330
331done
332
333exit 0
334