338 lines
7.6 KiB
Bash
Executable File
338 lines
7.6 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Multi-build script for testing compilation of all maintained
|
|
# configs of GDB.
|
|
|
|
# Copyright (C) 2002-2018 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Make certain that the script is not running in an internationalized
|
|
# environment.
|
|
LANG=c ; export LANG
|
|
LC_ALL=c ; export LC_ALL
|
|
|
|
usage()
|
|
{
|
|
cat <<EOF
|
|
Usage: gdb_mbuild.sh [ <options> ... ] <srcdir> <builddir>
|
|
Options:
|
|
-j <makejobs> Run <makejobs> 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 <regexp> 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:
|
|
<srcdir> Source code directory.
|
|
<builddir> Build directory.
|
|
Environment variables examined (with default if not defined):
|
|
MAKE (make)"
|
|
EOF
|
|
exit 1;
|
|
cat <<NOTYET
|
|
-b <maxbuilds> Run <maxbuild> builds in parallel.
|
|
On a single cpu machine, 1 is recommended.
|
|
NOTYET
|
|
}
|
|
|
|
### COMMAND LINE OPTIONS
|
|
|
|
makejobs=
|
|
maxbuilds=1
|
|
keepgoing=
|
|
force=false
|
|
targexp=""
|
|
verbose=0
|
|
keep=false
|
|
while test $# -gt 0
|
|
do
|
|
case "$1" in
|
|
-j )
|
|
# Number of parallel make jobs.
|
|
shift
|
|
test $# -ge 1 || usage
|
|
makejobs="-j $1"
|
|
;;
|
|
-b | -c )
|
|
# Number of builds to fire off in parallel.
|
|
shift
|
|
test $# -ge 1 || usage
|
|
maxbuilds=$1
|
|
;;
|
|
-k )
|
|
# Should we soldier on after the first build fails?
|
|
keepgoing=-k
|
|
;;
|
|
--keep )
|
|
keep=true
|
|
;;
|
|
-e )
|
|
# A regular expression for selecting targets
|
|
shift
|
|
test $# -ge 1 || usage
|
|
targexp="${targexp} -e ${1}"
|
|
;;
|
|
-f )
|
|
# Force a rebuild
|
|
force=true ;
|
|
;;
|
|
-v )
|
|
# Be more, and more, and more, verbose
|
|
verbose=`expr ${verbose} + 1`
|
|
;;
|
|
-* ) usage ;;
|
|
*) break ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
|
|
### COMMAND LINE PARAMETERS
|
|
|
|
if test $# -ne 2
|
|
then
|
|
usage
|
|
fi
|
|
|
|
# Convert these to absolute directory paths.
|
|
|
|
# Where the sources live
|
|
srcdir=`cd $1 && /bin/pwd` || exit 1
|
|
|
|
# Where the builds occur
|
|
builddir=`cd $2 && /bin/pwd` || exit 1
|
|
|
|
### ENVIRONMENT PARAMETERS
|
|
|
|
# Version of make to use
|
|
make=${MAKE:-make}
|
|
MAKE=${make}
|
|
export MAKE
|
|
|
|
|
|
# Where to look for the list of targets to test
|
|
maintainers=${srcdir}/gdb/MAINTAINERS
|
|
if [ ! -r ${maintainers} ]
|
|
then
|
|
echo Maintainers file ${maintainers} not found
|
|
exit 1
|
|
fi
|
|
|
|
# Get the list of targets and the build options
|
|
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}" = ""
|
|
then
|
|
grep -v -e broken -e OBSOLETE
|
|
else
|
|
grep ${targexp}
|
|
fi`
|
|
|
|
|
|
# Usage: fail <message> <test-that-should-succeed>. 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.
|
|
|
|
fail ()
|
|
{
|
|
msg="$1" ; shift
|
|
if test "$@"
|
|
then
|
|
echo "${target}: ${msg}"
|
|
if test "${keepgoing}" != ""
|
|
then
|
|
#exit 1
|
|
continue
|
|
else
|
|
kill $$
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
|
|
# Usage: log <level> <logfile>. Write standard input to <logfile> and
|
|
# stdout (if verbose >= level).
|
|
|
|
log ()
|
|
{
|
|
if test ${verbose} -ge $1
|
|
then
|
|
tee $2
|
|
else
|
|
cat > $2
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
# Warn the user of what is coming, print the list of targets
|
|
|
|
echo "$alltarg"
|
|
echo ""
|
|
|
|
|
|
# For each target, configure, build and test it.
|
|
|
|
echo "$alltarg" | while read target gdbopts simopts
|
|
do
|
|
|
|
trap "exit 1" 1 2 15
|
|
dir=${builddir}/${target}
|
|
|
|
# Should a scratch rebuild be forced, for perhaps the entire
|
|
# build be skipped?
|
|
|
|
if ${force}
|
|
then
|
|
echo forcing ${target} ...
|
|
rm -rf ${dir}
|
|
elif test -f ${dir}
|
|
then
|
|
echo "${target}"
|
|
continue
|
|
else
|
|
echo ${target} ...
|
|
fi
|
|
|
|
# Did the previous configure attempt fail? If it did
|
|
# restart from scratch.
|
|
|
|
if test -d ${dir} -a ! -r ${dir}/Makefile
|
|
then
|
|
echo ... removing partially configured ${target}
|
|
rm -rf ${dir}
|
|
if test -d ${dir}
|
|
then
|
|
echo "${target}: unable to remove directory ${dir}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# 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
|
|
then
|
|
# Default SIMOPTS to GDBOPTS.
|
|
test -z "${simopts}" && simopts="${gdbopts}"
|
|
# The config options
|
|
__target="--target=${target}"
|
|
__enable_gdb_build_warnings=`test -z "${gdbopts}" \
|
|
|| echo "--enable-gdb-build-warnings=${gdbopts}"`
|
|
__enable_sim_build_warnings=`test -z "${simopts}" \
|
|
|| echo "--enable-sim-build-warnings=${simopts}"`
|
|
__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
|
|
fi
|
|
fail "configure failed" ! -r Makefile
|
|
|
|
# Build, if not built.
|
|
|
|
if test ! -x gdb/gdb -a ! -x gdb/gdb.exe
|
|
then
|
|
# 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 succeeded (executable
|
|
# left around from previous build).
|
|
echo ... ${make} ${keepgoing} ${makejobs} ${target}
|
|
( ${make} ${keepgoing} ${makejobs} all-gdb || rm -f gdb/gdb gdb/gdb.exe
|
|
) 2>&1 | log 1 Build.log
|
|
fi
|
|
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 <<EOF > 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
|
|
do
|
|
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"
|
|
done >> 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}
|
|
then
|
|
:
|
|
else
|
|
rm -f ${target}.tmp
|
|
mv ${target}/Mbuild.log ${target}.tmp
|
|
rm -rf ${target}
|
|
mv ${target}.tmp ${target}
|
|
fi
|
|
|
|
# Success!
|
|
echo ... ${target} built
|
|
|
|
done
|
|
|
|
exit 0
|