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