#! /bin/sh # cobuild: Build something from a checked-out wavefront. # $Id$ ################################################### # Usage information ################################################### usage () { echo "Usage: $0 -m EMAIL_ADDRESS -i SOURCE_DIR -o OUTPUT_DIR -p PROJECT -r [cvs | p4 | svn | none] [ -c CHANGELIST ]" echo " A notification e-mail will be sent to EMAIL_ADDRESS" echo " Source code is in SOURCE_DIR" echo " A symlink tree is made in OUTPUT_DIR/src" echo " Build is done in OUTPUT_DIR/build" echo " Install is done in OUTPUT_DIR/install" echo "" echo " PROJECT is the name of the project to be built" echo "" echo " Revision control options:" echo " cvs checkout PROJECT from CVS repository" echo " svn checkout PROJECT from Subversion repository" echo " p4 checkout PROJECT from Perforce repository" echo " none use source directory as is, do not attempt to checkout" echo "" echo " CHANGELIST indicates Perforce change number to use" exit 1 } ################################################### # Set defaults ################################################### MAILTO=root CM_REPOSITORY=none ################################################### # Parse commande line ################################################### while getopts c:i:o:m:p:r: opt do case $opt in c) CHANGELIST="$OPTARG" ;; i) SOURCE_DIR=$OPTARG ;; o) OUTPUT_DIR=$OPTARG ;; m) MAILTO=$OPTARG ;; p) PROJECT=$OPTARG ;; r) CM_REPOSITORY=$OPTARG ;; *) usage ;; esac done if [ "x$OUTPUT_DIR" = "x" ] then usage fi if [ "x$SOURCE_DIR" = "x" ] then usage fi case "$CM_REPOSITORY" in p4|cvs|svn|none) ;; *) usage ;; esac ################################################### # Setup environment ################################################### if [ "x$CM_REPOSITORY" = "xp4" ] then P4CONFIG=.p4 export P4CONFIG fi case ":$PATH:" in *:/usr/local/bin:*) ;; *) PATH=/usr/local/bin:$PATH ;; esac TMPDIR=/var/tmp GNUMAKE=gmake LANG=C export MAILTO OUTPUT_DIR SOURCE_DIR TMPDIR GNUMAKE \ PATH LANG set -e umask 022 PIDFILE=$OUTPUT_DIR/build.pid CHGFILE=$OUTPUT_DIR/build.change LOGFILE=$OUTPUT_DIR/build.log ################################################### # Prepare build ################################################### # Take mutex. lockfile $PIDFILE.lock trap 'rm -f $PIDFILE.lock' 0 # Determine change level to be built. cd $SOURCE_DIR case "$CM_REPOSITORY" in p4) if [ "$CHANGELIST" = "" ]; then CHANGELIST=`p4 changes -m 1 ... | awk '{print \$2}'` fi CM_TAG="$CHANGELIST" ;; svn) if [ "$CHANGELIST" = "" ]; then CHANGELIST=`svn log --limit 1 | sed -n '2s/^r\([0-9]*\) .*$/\1/p'` fi CM_TAG="$CHANGELIST" ;; cvs) if [ "$CHANGELIST" = "" ]; then CM_TAG="HEAD" else CM_TAG="ch_$CHANGELIST" fi ;; none) CM_TAG="current" ;; esac export CHANGELIST CM_TAG # Kill any previous build, unless we know for a fact # that the build in porgress is building this change # or a more recent one. if [ -f $PIDFILE ] then OLDPID=`cat $PIDFILE` if [ "x$OLDPID" != x ] && ps -p $OLDPID > /dev/null then # Build in progress. if [ "$CHANGELIST" != "" && -f "$CHGFILE" ]; then if [ "`cat $CHGFILE`" -ge "$CHANGELIST" ] then # Already building this changelist or a more recent one. exit 0 fi fi # Interrupt current build kill $OLDPID > /dev/null 2>&1 || true fi fi # Here comes the hot builder. exec > $LOGFILE 2>&1 # Prepare execution. echo "---------- Starting build of ${PROJECT} at `date`" echo "---------- Syncing from repository $CM_REPOSITORY at $CM_TAG" ################################################### # Update files ################################################### case "$CM_REPOSITORY" in p4) p4 sync @$CM_TAG ;; cvs) cvs update -d -C -r$CM_TAG ;; svn) svn update -r$CM_TAG ;; *) echo "Using currently directory as is" ;; esac ################################################### # Launch build process ################################################### rungroup /bin/sh -c '( set -e sleep 10 echo "---------- Preparing source tree" cd $OUTPUT_DIR rm -fr src mkdir src mkdir build > /dev/null 2>&1 || true mkdir install > /dev/null 2>&1 || true cd src while read file do dir=`dirname "$file"` mkdir -p "$dir" if [ -f "$SOURCE_DIR/$file" ] then ln -s "$SOURCE_DIR/$file" "$file" fi done < $SOURCE_DIR/MANIFEST if [ ! -e testsuite ] then ln -s "$SOURCE_DIR/testsuite" . fi support/reconfig -w # At this point every file named in MANIFEST must exist while read file do if [ ! -f "$file" ] then echo "FATAL: MANIFEST file $file not found." exit 1 fi done < MANIFEST cd ../build echo "---------- Building" if [ -x $OUTPUT_DIR/src/configure ] then $OUTPUT_DIR/src/configure --disable-shared --enable-debug \ --with-proto-perso="giop soap srp" --with-appli-perso="corba moma" \ --with-corba-services="naming ir event notification time" --with-openssl --prefix=$OUTPUT_DIR/install fi && ${GNUMAKE} && ${GNUMAKE} install && cd examples && ${GNUMAKE} && cd ../docs && ${GNUMAKE} && ${GNUMAKE} install # && cd ../testsuite && ${GNUMAKE} # XXX configure is not processing testsuite diectory! RC=$? exit $RC )' & # The build is now running in background. Save PID and changelist #, # and release mutex. THISPID=$! echo $THISPID > $PIDFILE if [ "$CHANGELIST" != "" ]; then echo $CHANGELIST > $CHGFILE fi ################################################### # Analyze build output ################################################### trap '' 0 rm -f $PIDFILE.lock set +e wait $THISPID RC=$? set -e if [ $RC = 0 ] then echo "---------- Build completed successfully: `date`" STATUS="completed" MSG="Build completed successfully.\\nSee details at $OUTPUT_DIR/build.log" SUCCESS=true elif [ $RC -ge 128 ] then echo "---------- Build aborted by a signal: `date`" STATUS="aborted" MSG="The build process was interrupted by a signal." SUCCESS=true else echo "---------- BUILD FAILED: `date`" SUCCESS=false fi if $SUCCESS then echo -e "$MSG" | Mail -s "${PROJECT} build $CM_REPOSITORY $CM_TAG $STATUS" $MAILTO else cat $OUTPUT_DIR/build.log | Mail -s "${PROJECT} BUILD $CM_REPOSITORY $CM_TAG FAILED" $MAILTO fi lockfile $PIDFILE.lock THATPID=`cat $PIDFILE` if [ "$THATPID" = "$THISPID" ] then rm -f $PIDFILE fi rm -f $PIDFILE.lock