1130803Smarcel#!/bin/sh
2130803Smarcel
3130803Smarcel#  Multi-build script for testing compilation of all maintained
4130803Smarcel#  configs of GDB.
5130803Smarcel
6130803Smarcel#  Copyright 2002, 2003 Free Software Foundation, Inc.
7130803Smarcel
8130803Smarcel#  Contributed by Richard Earnshaw  (rearnsha@arm.com)
9130803Smarcel
10130803Smarcel#  This program is free software; you can redistribute it and/or modify
11130803Smarcel#  it under the terms of the GNU General Public License as published by
12130803Smarcel#  the Free Software Foundation; either version 2 of the License, or
13130803Smarcel#  (at your option) any later version.
14130803Smarcel
15130803Smarcel#  This program is distributed in the hope that it will be useful,
16130803Smarcel#  but WITHOUT ANY WARRANTY; without even the implied warranty of
17130803Smarcel#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18130803Smarcel#  GNU General Public License for more details.
19130803Smarcel
20130803Smarcel#  You should have received a copy of the GNU General Public License
21130803Smarcel#  along with this program; if not, write to the Free Software
22130803Smarcel#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23130803Smarcel
24130803Smarcelusage()
25130803Smarcel{
26130803Smarcel    cat <<EOF
27130803SmarcelUsage: gdb_mbuild.sh [ <options> ... ] <srcdir> <builddir>
28130803Smarcel Options:
29130803Smarcel   -j <makejobs>  Run <makejobs> in parallel.  Passed to make.
30130803Smarcel	          On a single cpu machine, 2 is recommended.
31130803Smarcel   -k             Keep going.  Do not stop after the first build fails.
32130803Smarcel   --keep         Keep builds.  Do not remove each build when finished.
33130803Smarcel   -e <regexp>    Regular expression for selecting the targets to build.
34130803Smarcel   -f             Force rebuild.  Even rebuild previously built directories.
35130803Smarcel   -v             Be more (and more, and more) verbose.
36130803Smarcel Arguments:
37130803Smarcel   <srcdir>       Source code directory.
38130803Smarcel   <builddir>     Build directory.
39130803Smarcel Environment variables examined (with default if not defined):
40130803Smarcel   MAKE (make)"
41130803SmarcelEOF
42130803Smarcel    exit 1;
43130803Smarcelcat <<NOTYET
44130803Smarcel  -b <maxbuilds> Run <maxbuild> builds in parallel.
45130803Smarcel		 On a single cpu machine, 1 is recommended.
46130803SmarcelNOTYET
47130803Smarcel}
48130803Smarcel
49130803Smarcel### COMMAND LINE OPTIONS
50130803Smarcel
51130803Smarcelmakejobs=
52130803Smarcelmaxbuilds=1
53130803Smarcelkeepgoing=
54130803Smarcelforce=false
55130803Smarceltargexp=""
56130803Smarcelverbose=0
57130803Smarcelkeep=false
58130803Smarcelwhile test $# -gt 0
59130803Smarceldo
60130803Smarcel    case "$1" in
61130803Smarcel    -j )
62130803Smarcel	# Number of parallel make jobs.
63130803Smarcel	shift
64130803Smarcel	test $# -ge 1 || usage
65130803Smarcel	makejobs="-j $1"
66130803Smarcel	;;
67130803Smarcel    -b | -c )
68130803Smarcel	# Number of builds to fire off in parallel.
69130803Smarcel	shift
70130803Smarcel	test $# -ge 1 || usage
71130803Smarcel	maxbuilds=$1
72130803Smarcel	;;
73130803Smarcel    -k )
74130803Smarcel	# Should we soldier on after the first build fails?
75130803Smarcel	keepgoing=-k
76130803Smarcel	;;
77130803Smarcel    --keep )
78130803Smarcel        keep=true
79130803Smarcel	;;
80130803Smarcel    -e )
81130803Smarcel	# A regular expression for selecting targets
82130803Smarcel	shift
83130803Smarcel	test $# -ge 1 || usage
84130803Smarcel	targexp="${targexp} -e ${1}"
85130803Smarcel	;;
86130803Smarcel    -f )
87130803Smarcel	# Force a rebuild
88130803Smarcel	force=true ;
89130803Smarcel	;;
90130803Smarcel    -v )
91130803Smarcel	# Be more, and more, and more, verbose
92130803Smarcel	verbose=`expr ${verbose} + 1`
93130803Smarcel	;;
94130803Smarcel    -* ) usage ;;
95130803Smarcel    *) break ;;
96130803Smarcel    esac
97130803Smarcel    shift
98130803Smarceldone
99130803Smarcel
100130803Smarcel
101130803Smarcel### COMMAND LINE PARAMETERS
102130803Smarcel
103130803Smarcelif test $# -ne 2
104130803Smarcelthen
105130803Smarcel    usage
106130803Smarcelfi
107130803Smarcel
108130803Smarcel# Convert these to absolute directory paths.
109130803Smarcel
110130803Smarcel# Where the sources live
111130803Smarcelsrcdir=`cd $1 && /bin/pwd` || exit 1
112130803Smarcel
113130803Smarcel# Where the builds occur
114130803Smarcelbuilddir=`cd $2 && /bin/pwd` || exit 1
115130803Smarcel
116130803Smarcel### ENVIRONMENT PARAMETERS
117130803Smarcel
118130803Smarcel# Version of make to use
119130803Smarcelmake=${MAKE:-make}
120130803SmarcelMAKE=${make}
121130803Smarcelexport MAKE
122130803Smarcel
123130803Smarcel
124130803Smarcel# Where to look for the list of targets to test
125130803Smarcelmaintainers=${srcdir}/gdb/MAINTAINERS
126130803Smarcelif [ ! -r ${maintainers} ]
127130803Smarcelthen
128130803Smarcel    echo Maintainers file ${maintainers} not found
129130803Smarcel    exit 1
130130803Smarcelfi
131130803Smarcel
132130803Smarcel# Get the list of targets and the build options
133130803Smarcelalltarg=`cat ${maintainers} | tr -s '[\t]' '[ ]' | sed -n '
134130803Smarcel/^[ ]*[-a-z0-9\.]*[ ]*[(]*--target=.*/ !d
135130803Smarcels/^.*--target=//
136130803Smarcels/).*$//
137130803Smarcelh
138130803Smarcel:loop
139130803Smarcel  g
140130803Smarcel  /^[^ ]*,/ !b end
141130803Smarcel  s/,[^ ]*//
142130803Smarcel  p
143130803Smarcel  g
144130803Smarcel  s/^[^,]*,//
145130803Smarcel  h
146130803Smarcelb loop
147130803Smarcel:end
148130803Smarcelp
149130803Smarcel' | if test "${targexp}" = ""
150130803Smarcelthen
151130803Smarcel    grep -v -e broken -e OBSOLETE
152130803Smarcelelse
153130803Smarcel    grep ${targexp}
154130803Smarcelfi`
155130803Smarcel
156130803Smarcel
157130803Smarcel# Usage: fail <message> <test-that-should-succeed>.  Should the build
158130803Smarcel# fail?  If the test is true, and we don't want to keep going, print
159130803Smarcel# the message and shoot everything in sight and abort the build.
160130803Smarcel
161130803Smarcelfail ()
162130803Smarcel{
163130803Smarcel    msg="$1" ; shift
164130803Smarcel    if test "$@"
165130803Smarcel    then
166130803Smarcel	echo "${target}: ${msg}"
167130803Smarcel	if test "${keepgoing}" != ""
168130803Smarcel	then
169130803Smarcel	    #exit 1
170130803Smarcel	    continue
171130803Smarcel	else
172130803Smarcel	    kill $$
173130803Smarcel	    exit 1
174130803Smarcel	fi
175130803Smarcel    fi
176130803Smarcel}
177130803Smarcel
178130803Smarcel
179130803Smarcel# Usage: log <level> <logfile>.  Write standard input to <logfile> and
180130803Smarcel# stdout (if verbose >= level).
181130803Smarcel
182130803Smarcellog ()
183130803Smarcel{
184130803Smarcel    if test ${verbose} -ge $1
185130803Smarcel    then
186130803Smarcel	tee $2
187130803Smarcel    else
188130803Smarcel	cat > $2
189130803Smarcel    fi
190130803Smarcel}
191130803Smarcel
192130803Smarcel
193130803Smarcel
194130803Smarcel# Warn the user of what is comming, print the list of targets
195130803Smarcel
196130803Smarcelecho "$alltarg"
197130803Smarcelecho ""
198130803Smarcel
199130803Smarcel
200130803Smarcel# For each target, configure, build and test it.
201130803Smarcel
202130803Smarcelecho "$alltarg" | while read target gdbopts simopts
203130803Smarceldo
204130803Smarcel
205130803Smarcel    trap "exit 1"  1 2 15
206130803Smarcel    dir=${builddir}/${target}
207130803Smarcel
208130803Smarcel    # Should a scratch rebuild be forced, for perhaphs the entire
209130803Smarcel    # build be skipped?
210130803Smarcel
211130803Smarcel    if ${force}
212130803Smarcel    then
213130803Smarcel	echo forcing ${target} ...
214130803Smarcel	rm -rf ${dir}
215130803Smarcel    elif test -f ${dir}
216130803Smarcel    then
217130803Smarcel	echo "${target}"
218130803Smarcel	continue
219130803Smarcel    else
220130803Smarcel	echo ${target} ...
221130803Smarcel    fi
222130803Smarcel
223130803Smarcel    # Did the previous configure attempt fail?  If it did
224130803Smarcel    # restart from scratch.
225130803Smarcel
226130803Smarcel    if test -d ${dir} -a ! -r ${dir}/Makefile
227130803Smarcel    then
228130803Smarcel	echo ... removing partially configured ${target}
229130803Smarcel	rm -rf ${dir}
230130803Smarcel	if test -d ${dir}
231130803Smarcel	then
232130803Smarcel	    echo "${target}: unable to remove directory ${dir}"
233130803Smarcel	    exit 1
234130803Smarcel	fi
235130803Smarcel    fi
236130803Smarcel
237130803Smarcel    # From now on, we're in this target's build directory
238130803Smarcel
239130803Smarcel    mkdir -p ${dir}
240130803Smarcel    cd ${dir} || exit 1
241130803Smarcel
242130803Smarcel    # Configure, if not already.  Should this go back to being
243130803Smarcel    # separate and done in parallel?
244130803Smarcel
245130803Smarcel    if test ! -r Makefile
246130803Smarcel    then
247130803Smarcel	# Default SIMOPTS to GDBOPTS.
248130803Smarcel	test -z "${simopts}" && simopts="${gdbopts}"
249130803Smarcel	# The config options
250130803Smarcel	__target="--target=${target}"
251130803Smarcel	__enable_gdb_build_warnings=`test -z "${gdbopts}" \
252130803Smarcel	    || echo "--enable-gdb-build-warnings=${gdbopts}"`
253130803Smarcel	__enable_sim_build_warnings=`test -z "${simopts}" \
254130803Smarcel	    || echo "--enable-sim-build-warnings=${simopts}"`
255130803Smarcel	__configure="${srcdir}/configure \
256130803Smarcel	    ${__target} \
257130803Smarcel	    ${__enable_gdb_build_warnings} \
258130803Smarcel	    ${__enable_sim_build_warnings}"
259130803Smarcel	echo ... ${__configure}
260130803Smarcel	trap "echo Removing partially configured ${dir} directory ...; rm -rf ${dir}; exit 1" 1 2 15
261130803Smarcel	${__configure} 2>&1 | log 2 Config.log
262130803Smarcel	trap "exit 1"  1 2 15
263130803Smarcel    fi
264130803Smarcel    fail "configure failed" ! -r Makefile
265130803Smarcel 
266130803Smarcel    # Build, if not built.
267130803Smarcel
268130803Smarcel    if test ! -x gdb/gdb -a ! -x gdb/gdb.exe
269130803Smarcel    then
270130803Smarcel	# Iff the build fails remove the final build target so that
271130803Smarcel	# the follow-on code knows things failed.  Stops the follow-on
272130803Smarcel	# code thinking that a failed rebuild succedded (executable
273130803Smarcel	# left around from previous build).
274130803Smarcel	echo ... ${make} ${keepgoing} ${makejobs} ${target}
275130803Smarcel	( ${make} ${keepgoing} ${makejobs} all-gdb || rm -f gdb/gdb gdb/gdb.exe
276130803Smarcel	) 2>&1 | log 1 Build.log
277130803Smarcel    fi
278130803Smarcel    fail "compile failed" ! -x gdb/gdb -a ! -x gdb/gdb.exe
279130803Smarcel 
280130803Smarcel    # Check that the built GDB can at least print it's architecture.
281130803Smarcel
282130803Smarcel    echo ... run ${target}
283130803Smarcel    rm -f core gdb.core ${dir}/gdb/x
284130803Smarcel    cat <<EOF > x
285130803Smarcelmaint print architecture
286130803Smarcelquit
287130803SmarcelEOF
288130803Smarcel    ./gdb/gdb -batch -nx -x x 2>&1 | log 1 Gdb.log
289130803Smarcel    fail "gdb dumped core" -r core -o -r gdb.core
290130803Smarcel    fail "gdb printed no output" ! -s Gdb.log
291130803Smarcel    grep -e internal-error Gdb.log && fail "gdb panic" 1
292130803Smarcel
293130803Smarcel    echo ... cleanup ${target}
294130803Smarcel
295130803Smarcel    # Create a sed script that cleans up the output from GDB.
296130803Smarcel    rm -f mbuild.sed
297130803Smarcel    touch mbuild.sed || exit 1
298130803Smarcel    # Rules to replace <0xNNNN> with the corresponding function's
299130803Smarcel    # name.
300130803Smarcel    sed -n -e '/<0x0*>/d' -e 's/^.*<0x\([0-9a-f]*\)>.*$/0x\1/p' Gdb.log \
301130803Smarcel    | sort -u \
302130803Smarcel    | while read addr
303130803Smarcel    do
304130803Smarcel	func="`addr2line -f -e ./gdb/gdb -s ${addr} | sed -n -e 1p`"
305130803Smarcel	test ${verbose} -gt 0 && echo "${addr} ${func}" 1>&2
306130803Smarcel	echo "s/<${addr}>/<${func}>/g"
307130803Smarcel    done >> mbuild.sed
308130803Smarcel    # Rules to strip the leading paths off of file names.
309130803Smarcel    echo 's/"\/.*\/gdb\//"gdb\//g' >> mbuild.sed
310130803Smarcel    # Run the script
311130803Smarcel    sed -f mbuild.sed Gdb.log > Mbuild.log
312130803Smarcel
313130803Smarcel    # Replace the build directory with a file as semaphore that stops
314130803Smarcel    # a rebuild. (should the logs be saved?)
315130803Smarcel
316130803Smarcel    cd ${builddir}
317130803Smarcel
318130803Smarcel    if ${keep}
319130803Smarcel    then
320130803Smarcel	:
321130803Smarcel    else
322130803Smarcel	rm -f ${target}.tmp
323130803Smarcel	mv ${target}/Mbuild.log ${target}.tmp
324130803Smarcel	rm -rf ${target}
325130803Smarcel	mv ${target}.tmp ${target}
326130803Smarcel    fi
327130803Smarcel
328130803Smarcel    # Success!
329130803Smarcel    echo ... ${target} built
330130803Smarcel
331130803Smarceldone
332130803Smarcel
333130803Smarcelexit 0
334