#!/bin/bash # TOPDIR: set this to the directory containing # your 'mono' and 'mcs' directories. Do NOT use '~' here. TOPDIR=$HOME/mono # BACKUP: initially this directory should contain a working install of mono. # this directory should minimally contain the 'bin' and 'lib' dirs. # after each successful build, the results are placed in here. BACKUP=$TOPDIR/install.bak # INSTALL: this is used as the install directory for # the various stages of the build. INSTALL=$TOPDIR/install # SENDMAIL: uncomment this line if you want to send notifications. # be careful to check the recipients below before running this script! SENDMAIL=$TOPDIR/mcs/tools/tinderbox/smtp # EMAIL_*: notification addresses. please change these before running! EMAIL_FATAL="piersh@friskit.com" EMAIL_MESSAGE="mono-patches@lists.ximian.com" #EMAIL_MESSAGE="piersh@friskit.com" #EMAIL_MESSAGE="mono-hackers-list@ximian.com" EMAIL_FROM="piersh@friskit.com" EMAIL_CC="-c mono-hackers-list@lists.ximian.com" EMAIL_HOST="zeus.sfhq.friskit.com" LOGBASE=$TOPDIR/.build.log LOG=$LOGBASE.txt LOGPREV=$LOGBASE.prev LOGFATAL=$LOGBASE.fatal LOGDATE=$TOPDIR/.build.date LOGLOG=$TOPDIR/.build.log.log BUILDMSG=$TOPDIR/.build.msg export LOGDATE DELAY_SUCCESS=5m # wait after a successful build DELAY_CHECK_BROKEN=5m # wait while verifying the build is broken DELAY_STILL_BROKEN=3m # wait while waiting for fix DELAY_BROKEN=5m # wait after notification sent FILTER_LOG="sed -e 's/^in <0x[0-9a-z]*>//' -e 's/:[0-9]*): WARNING \*\*:/): WARNING **/' -e 's/^\[[0-9][0-9]*:[0-9][0-9]*\] - .*//' -e 's/^[0-9][0-9]* - Member cache//' -e 's/^[0-9][0-9]* - Misc counter//' -e 's/: [0-9]* Trace\/breakpoint/ : Trace\/breakpoint/' -e 's/Needed to allocate blacklisted block at 0x[0-9a-f]*//'" function fatal () { $SENDMAIL -h $EMAIL_HOST -f $EMAIL_FROM -t $EMAIL_FATAL -a $LOGFATAL -s "[MONOBUILD] FATAL ERROR (`uname -s -m`)" echo FATAL: `date` >> $LOGLOG echo FATAL ERROR exit 1 } function build_mono () { # try to build echo building... cd $TOPDIR rm -f $LOGFATAL touch $LOGFATAL [ -f $LOG ] && mv $LOG $LOGPREV touch $LOG # restore tools from backup rm -fr $INSTALL cp -a $BACKUP $INSTALL # update from CVS cvs -z3 update -APd mcs mono 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # clean mcs cd $TOPDIR/mcs make -f makefile.gnu clean 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # build JAY cd $TOPDIR/mcs/jay make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # build MCS compiler cd $TOPDIR/mcs/mcs make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # build CORLIB with old tools cd $TOPDIR/mcs/class/corlib make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # copy new MCS and CORLIB to build tools cp -f $TOPDIR/mcs/class/lib/corlib.dll $INSTALL/lib/ cp -f $TOPDIR/mcs/mcs/mcs.exe $INSTALL/bin/ cd $TOPDIR/mono # configure mono build rm -f config.cache ./autogen.sh --prefix=$INSTALL 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # clean mono make clean 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # build mono make 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # install runtime cd $TOPDIR/mono/mono make install 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # clean/make runtime libraries/tools cd $TOPDIR/mcs make -f makefile.gnu clean 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # retrieve runtime libraries cd $TOPDIR/mono/runtime rm -f *.dll *.exe # install everything cd $TOPDIR/mono make install 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # test mcs self-build cd $TOPDIR/mcs/mcs make -f makefile.gnu clean 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # test corlib self-build cd $TOPDIR/mcs/class/corlib make -f makefile.gnu clean 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 make -f makefile.gnu 2>&1 | tee -a $LOG [ $PIPESTATUS == "0" ] || return 1 # it worked, backup build tools rm -fr $BACKUP cp -a $INSTALL $BACKUP return 0 } function compare_logs () { touch $LOG $LOGPREV echo Comparing build logs eval $FILTER_LOG $LOG > $LOG.tmp eval $FILTER_LOG $LOGPREV > $LOGPREV.tmp diff -b --brief $LOG.tmp $LOGPREV.tmp } function build_fixed () { echo "Build fixed: `date`" > $BUILDMSG echo "Previous breakage: `cat .build.date.last_fail`" >> $BUILDMSG echo "Previous build: `cat .build.date.last_success`" >> $BUILDMSG echo >> $BUILDMSG $SENDMAIL -h $EMAIL_HOST -f $EMAIL_FROM -t $EMAIL_MESSAGE $EMAIL_CC -s "[MONOBUILD] fixed (`uname -s -m`)" -m $BUILDMSG rm -f $BUILDMSG } function build_failed () { echo "Build broken: `date`" > $BUILDMSG echo "Broken since: `cat .build.date.last_fail`" >> $BUILDMSG echo "Previous build: `cat .build.date.last_success`" >> $BUILDMSG echo >> $BUILDMSG sed -e 's/$/ /' < $LOG > errors.txt tail -25 errors.txt >> $BUILDMSG rm -f errors.txt.gz gzip errors.txt $SENDMAIL -h $EMAIL_HOST -f $EMAIL_FROM -t $EMAIL_MESSAGE $EMAIL_CC -a errors.txt.gz -s "[MONOBUILD] broken (`uname -s -m`)" -m $BUILDMSG rm -f $BUILDMSG errors.txt.gz } function stabilize () { cd $TOPDIR while ! compare_logs ; do date > $LOGDATE.last_fail echo "|||||||||||||||||||||||||" echo "|||||| LOGS DIFFER ||||||" echo "|||||||||||||||||||||||||" echo CHECK: `date` >> $LOGLOG echo sleeping for $DELAY_CHECK_BROKEN sleep $DELAY_CHECK_BROKEN if build_mono ; then return 0 fi cd $TOPDIR done return 1 } [ -f $LOGPREV ] && mv $LOGPREV $LOG while [ 1 ] ; do cd $TOPDIR if build_mono ; then cd $TOPDIR echo "|||||||||||||||||||||||||" echo "|||| BUILD SUCCEEDED ||||" echo "|||||||||||||||||||||||||" echo SUCCESS: `date` >> $LOGLOG date > $LOGDATE.last_success echo sleeping for $DELAY_SUCCESS sleep $DELAY_SUCCESS else if ! stabilize ; then build_failed echo "||||||||||||||||||||||" echo "|||| BUILD BROKEN ||||" echo "||||||||||||||||||||||" echo BROKEN: `date` >> $LOGLOG date > $LOGDATE.last_fail echo sleeping for $DELAY_BROKEN sleep $DELAY_BROKEN until build_mono ; do cd $TOPDIR echo "||||||||||||||||||||||||||||" echo "|||| BUILD STILL BROKEN ||||" echo "||||||||||||||||||||||||||||" echo STILL BROKEN: `date` >> $LOGLOG date > $LOGDATE.last_fail echo sleeping for $DELAY_STILL_BROKEN sleep $DELAY_STILL_BROKEN done cd $TOPDIR build_fixed echo "|||||||||||||||||||||" echo "|||| BUILD FIXED ||||" echo "|||||||||||||||||||||" echo FIXED: `date` >> $LOGLOG date > $LOGDATE.last_success echo sleeping for $DELAY_SUCCESS sleep $DELAY_SUCCESS fi fi done