#!/bin/sh # Multi-build script for testing compilation of all maintained # configs of GDB. # Copyright 2002, 2003 Free Software Foundation, Inc. # Contributed by Richard Earnshaw (rearnsha@arm.com) # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA proc usage { cat << """ Usage: gdb_mbuild.sh [ ... ] Options: -j Run in parallel. Passed to make. On a single cpu machine, 2 is recommended. -k Keep going. Do not stop after the first build fails. --keep Keep builds. Do not remove each build when finished. -e Regular expression for selecting the targets to build. -f Force rebuild. Even rebuild previously built directories. -v Be more (and more, and more) verbose. Arguments: Source code directory. Build directory. Environment variables examined (with default if not defined): MAKE (make)" """ exit 1; cat << """ -b Run builds in parallel. On a single cpu machine, 1 is recommended. """ } ### COMMAND LINE OPTIONS setglobal makejobs = '' setglobal maxbuilds = '1' setglobal keepgoing = '' setglobal force = 'false' setglobal targexp = ''"" setglobal verbose = '0' setglobal keep = 'false' while test $# -gt 0 { match $1 { with -j # Number of parallel make jobs. shift test $Argc -ge 1 || usage setglobal makejobs = ""-j $1"" with -b | -c # Number of builds to fire off in parallel. shift test $Argc -ge 1 || usage setglobal maxbuilds = $1 with -k # Should we soldier on after the first build fails? setglobal keepgoing = '-k' with --keep setglobal keep = 'true' with -e # A regular expression for selecting targets shift test $Argc -ge 1 || usage setglobal targexp = ""$(targexp) -e $(1)"" with -f # Force a rebuild setglobal force = 'true' ; with -v # Be more, and more, and more, verbose setglobal verbose = $[expr $(verbose) + 1] with -* usage with * break } shift } ### COMMAND LINE PARAMETERS if test $Argc -ne 2 { usage } # Convert these to absolute directory paths. # Where the sources live setglobal srcdir = $[cd $1 && /bin/pwd] || exit 1 # Where the builds occur setglobal builddir = $[cd $2 && /bin/pwd] || exit 1 ### ENVIRONMENT PARAMETERS # Version of make to use setglobal make = $(MAKE:-make) setglobal MAKE = $(make) export MAKE # Where to look for the list of targets to test setglobal maintainers = "$(srcdir)/gdb/MAINTAINERS" if test ! -r $(maintainers) { echo Maintainers file $(maintainers) not found exit 1 } # Get the list of targets and the build options setglobal alltarg = $[cat $(maintainers) | tr -s '[\t]' '[ ]' | sed -n ' /^[ ]*[-a-z0-9\.]*[ ]*[(]*--target=.*/ !d s/^.*--target=// s/).*$// h :loop g /^[^ ]*,/ !b end s/,[^ ]*// p g s/^[^,]*,// h b loop :end p ' | if test $(targexp) = "" { grep -v -e broken -e OBSOLETE } else { grep $(targexp) }] # Usage: fail . Should the build # fail? If the test is true, and we don't want to keep going, print # the message and shoot everything in sight and abort the build. proc fail { setglobal msg = $1 ; shift if test @Argv { echo "$(target): $(msg)" if test $(keepgoing) != "" { #exit 1 continue } else { kill $Pid exit 1 } } } # Usage: log . Write standard input to and # stdout (if verbose >= level). proc log { if test $(verbose) -ge $1 { tee $2 } else { cat > $2 } } # Warn the user of what is comming, print the list of targets echo $alltarg echo "" # For each target, configure, build and test it. echo $alltarg | while read target gdbopts simopts { trap "exit 1" 1 2 15 setglobal dir = "$(builddir)/$(target)" # Should a scratch rebuild be forced, for perhaphs the entire # build be skipped? if $(force) { echo forcing $(target) ... rm -rf $(dir) } elif test -f $(dir) { echo $(target) continue } else { echo $(target) ... } # Did the previous configure attempt fail? If it did # restart from scratch. if test -d $(dir) -a ! -r $(dir)/Makefile { echo ... removing partially configured $(target) rm -rf $(dir) if test -d $(dir) { echo "$(target): unable to remove directory $(dir)" exit 1 } } # From now on, we're in this target's build directory mkdir -p $(dir) cd $(dir) || exit 1 # Configure, if not already. Should this go back to being # separate and done in parallel? if test ! -r Makefile { # Default SIMOPTS to GDBOPTS. test -z $(simopts) && setglobal simopts = $(gdbopts) # The config options setglobal __target = ""--target=$(target)"" setglobal __enable_gdb_build_warnings = $[test -z $(gdbopts) \ || echo "--enable-gdb-build-warnings=$(gdbopts)] setglobal __enable_sim_build_warnings = $[test -z $(simopts) \ || echo "--enable-sim-build-warnings=$(simopts)] setglobal __configure = ""$(srcdir)/configure \ $(__target) \ $(__enable_gdb_build_warnings) \ $(__enable_sim_build_warnings)"" echo ... $(__configure) trap "echo Removing partially configured $(dir) directory ...; rm -rf $(dir); exit 1" 1 2 15 $(__configure) !2 > !1 | log 2 Config.log trap "exit 1" 1 2 15 } fail "configure failed" ! -r Makefile # Build, if not built. if test ! -x gdb/gdb -a ! -x gdb/gdb.exe { # Iff the build fails remove the final build target so that # the follow-on code knows things failed. Stops the follow-on # code thinking that a failed rebuild succedded (executable # left around from previous build). echo ... $(make) $(keepgoing) $(makejobs) $(target) shell { $(make) $(keepgoing) $(makejobs) all-gdb || rm -f gdb/gdb gdb/gdb.exe } 2>&1 | log 1 Build.log } fail "compile failed" ! -x gdb/gdb -a ! -x gdb/gdb.exe # Check that the built GDB can at least print it's architecture. echo ... run $(target) rm -f core gdb.core $(dir)/gdb/x cat << """ > x maint print architecture quit """ > x maint print architecture quit EOF ./gdb/gdb -batch -nx -x x !2 > !1 | log 1 Gdb.log fail "gdb dumped core" -r core -o -r gdb.core fail "gdb printed no output" ! -s Gdb.log grep -e internal-error Gdb.log && fail "gdb panic" 1 echo ... cleanup $(target) # Create a sed script that cleans up the output from GDB. rm -f mbuild.sed touch mbuild.sed || exit 1 # Rules to replace <0xNNNN> with the corresponding function's # name. sed -n -e '/<0x0*>/d' -e 's/^.*<0x\([0-9a-f]*\)>.*$/0x\1/p' Gdb.log \ | sort -u \ | while read addr { setglobal func = $[addr2line -f -e ./gdb/gdb -s $(addr) | sed -n -e 1p] test $(verbose) -gt 0 && echo "$(addr) $(func)" !1 > !2 echo "s/<$(addr)>/<$(func)>/g" } >> mbuild.sed # Rules to strip the leading paths off of file names. echo 's/"\/.*\/gdb\//"gdb\//g' >> mbuild.sed # Run the script sed -f mbuild.sed Gdb.log > Mbuild.log # Replace the build directory with a file as semaphore that stops # a rebuild. (should the logs be saved?) cd $(builddir) if $(keep) { : } else { rm -f $(target).tmp mv $(target)/Mbuild.log $(target).tmp rm -rf $(target) mv $(target).tmp $(target) } # Success! echo ... $(target) built } exit 0