1 #!/bin/sh -*- mode: shell-script; sh-indentation: 8; indent-tabs-mode: t; -*-
3 # build_farm -- distributed build/test architecture for samba, rsync, etc
5 # Copyright (C) 2001 by Andrew Tridgell <tridge@samba.org>
6 # Copyright (C) 2001 by Andrew Bartlett <abartlet@samba.org>
7 # Copyright (C) 2001, 2003 by Martin Pool <mbp@samba.org>
9 # default maximum runtime for any command
11 # default maximum memory size (100M) for any command
13 RUN_FROM_BUILD_FARM=yes
14 export RUN_FROM_BUILD_FARM
18 build_test_fns_id='$Id$'
20 #############################
21 # build a signature of a tree, used to see if we
27 find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v '.svn' | grep -v version.h | sort | xargs sum > $sum_tree_sum
28 sum build_test build_test.fns >> $sum_tree_sum
30 if [ -f "$host.fns" ]; then
31 sum $host.fns >> $sum_tree_sum
33 sum generic.fns >> $sum_tree_sum
35 if [ -f "$test_root/$tree.svn" ]; then
36 sum "$test_root/$tree.svn" >> $sum_tree_sum
38 for d in $deptrees; do
39 if [ -f "$test_root/$d.svn" ]; then
40 sum "$test_root/$d.svn" >> $sum_tree_sum
45 #############################
46 # send the logs to the master site
48 if [ "$nologreturn" = "yes" ]; then
49 echo "skipping log transfer"
55 chmod 0644 "$log" "$err"
58 if [ "`uname`" = "FreeBSD" ]; then
59 XARGS_I="xargs -I '{}' -R -1"
61 if [ "`uname`" = "Darwin" ]; then
62 XARGS_I="xargs -I '{}' -R -1"
64 find $log -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
65 find $err -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
67 rsync $* -ct -q --password-file=.password -z --timeout=200 \
68 "$log" "$err" $host@build.samba.org::build_farm_data/
72 #############################
73 # send the logs when they haven't changed
74 # the aim is to just update the servers timestamp.
75 # sending with a very large rsync block size does this
76 # with minimal network traffic
79 send_logs "$1" "$2" -B 10000000
82 ############################
83 # fetch the latest copy of the tree
85 if [ "$norsync" = "yes" ]; then
86 echo "skipping tree transfer"
89 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --delete-excluded -q --partial --timeout=200 -crlpz --delete --ignore-errors \
90 samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
91 echo "transferred $fetchtree OK"
93 echo "transfer of $fetchtree failed code $?"
100 ############################
101 # fetch the latest copy of the svn entries file
104 # skip products still in CVS.
106 ccache | distcc | rsync)
112 if [ "$norsync" = "yes" ]; then
113 echo "skipping svn transfer"
115 if [ -r $test_root/$tree.svn ]; then
116 rm -f $test_root/$tree.svn.old
117 mv $test_root/$tree.svn $test_root/$tree.svn.old
119 rsync -q --timeout=200 -clz --ignore-errors \
120 samba.org::ftp/unpacked/$tree/.svn/entries $test_root/$tree.svn.tmp
121 chmod u+w $test_root/$tree.svn.tmp
122 sort -u < $test_root/$tree.svn.tmp > $test_root/$tree.svn
123 rm -f $test_root/$tree.svn.tmp
125 if [ -r $test_root/$tree.svn ]; then
133 ############################
134 # grab a lock file. Not atomic, but close :)
135 # tries to cope with NFS
137 if [ -z "$lock_root" ]; then
141 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
142 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
144 if [ "$pid" = "$$" ]; then
145 locknesting=`expr $locknesting + 1`
146 echo "lock nesting now $locknesting"
150 if test -f "$lckf"; then
151 test $machine = $host || {
152 echo "lock file $lckf is valid for other machine $machine"
156 echo "lock file $lckf is valid for process $pid"
159 echo "stale lock file $lckf for $machine:$pid"
163 echo "$host:$$" > "$lckf"
167 ############################
170 if [ -z "$lock_root" ]; then
173 if [ "$locknesting" != "0" ]; then
174 locknesting=`expr $locknesting - 1`
175 echo "lock nesting now $locknesting"
182 ############################
183 # run make, and print trace
192 # some trees don't need as much time
194 rsync | tdb | talloc | libreplace | ccache | distcc)
195 if [ "$compiler" != "checker" ]; then
196 MMTIME=`expr $MMTIME / 5`
203 if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
205 ./timelimit $MMTIME "$MAKE" "$t"
208 # we can parallelize everything and all targets
209 if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
210 echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
211 ./timelimit $MMTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
215 ./timelimit $MMTIME "$MAKE" "$t"
220 if [ $status != 0 ]; then
229 ############################
232 if [ ! -x $srcdir/configure ]; then
233 ls -l $srcdir/configure
234 echo "$srcdir/configure is missing"
236 echo "CONFIGURE STATUS: $cstatus"
239 echo "CFLAGS=$CFLAGS"
240 echo configure options: $config_and_prefix
241 echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
242 CC="$CCACHE $compiler"
244 ./timelimit $MAXTIME $srcdir/configure $config_and_prefix
246 echo "CONFIGURE STATUS: $cstatus"
247 if [ -f config.h ]; then
248 echo "contents of config.h:"
251 if [ -f include/config.h ]; then
252 echo "contents of include/config.h:"
258 ############################
259 # show the configure log
260 action_config_log() {
261 if [ ! -f config.log ]; then
264 echo "contents of config.log:"
272 rsync -a --delete $Tsrc/ $Tdst
275 s4selftest_create() {
276 lock_file "s4selftest.lck" || {
281 mkdir -p $s4selftest/source
283 copy_dir $builddir/bin $s4selftest/source/bin || {
285 unlock_file "s4selftest.lck";
289 copy_dir $srcdir/setup $s4selftest/source/setup || {
291 unlock_file "s4selftest.lck";
295 copy_dir $srcdir/../testprogs $s4selftest/testprogs || {
297 unlock_file "s4selftest.lck";
301 copy_dir $srcdir/selftest $s4selftest/source/selftest || {
303 unlock_file "s4selftest.lck";
307 copy_dir $srcdir/script $s4selftest/source/script || {
309 unlock_file "s4selftest.lck";
313 mkdir -p $s4selftest/source/scripting || {
315 unlock_file "s4selftest.lck";
319 copy_dir $srcdir/scripting/libjs $s4selftest/source/scripting/libjs || {
321 unlock_file "s4selftest.lck";
325 unlock_file "s4selftest.lck"
328 s4selftest_update() {
329 lock_file "s4selftest.lck" || {
333 copy_dir $s4selftest $s4selftest.$tree.$compiler.$$ || {
334 rm -rf $s4selftest.$tree.$compiler.$$;
335 unlock_file "s4selftest.lck";
339 rm -rf $s4selftest.$tree.$compiler
340 mv $s4selftest.$tree.$compiler.$$ $s4selftest.$tree.$compiler
342 unlock_file "s4selftest.lck"
345 ############################
352 if test x"$bstatus" != x"0"; then
353 # the 2nd 'make everything' is to work around a bug
359 if test x"$bstatus" != x"0"; then
364 if test x"$bstatus" = x"0"; then
370 do_make proto everything torture
379 echo "BUILD STATUS: $bstatus"
384 ############################
385 # show static analysis results
386 action_cc_checker() {
388 # default to passing the cc_checker
391 if [ -f ibm_checker.out ]; then
393 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
396 echo "CC_CHECKER STATUS: $cccstatus"
400 ############################
403 if [ -d $prefix ]; then
404 if [ "$noclean" != "yes" ]; then
411 echo "INSTALL STATUS: $istatus"
415 ############################
417 action_test_samba() {
420 return "$totalstatus"
423 action_test_generic() {
428 echo "TEST STATUS: $totalstatus"
429 return "$totalstatus"
432 action_test_lorikeet_heimdal() {
435 SOCKET_WRAPPER_DIR=`pwd`/sw
436 mkdir $SOCKET_WRAPPER_DIR
437 export SOCKET_WRAPPER_DIR
441 export SOCKET_WRAPPER_DIR
442 echo "TEST STATUS: $totalstatus"
443 return "$totalstatus"
447 #############################
448 # attempt some basic tests of functionaility
449 # starting as basic as possible, and getting incresingly complex
452 # Samba needs crufty code of its own for backward
453 # compatiblity. I think a better way to do this in the future
454 # is to just call 'make installcheck'.
457 # echo "testing of samba_3* disabled until cause of runaway processes found (tridge - 7th sep 2006)"
459 samba*|smb-build|pidl)
463 action_test_lorikeet_heimdal
471 ###########################
472 # do a test build of a particular tree
480 if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && ccache -V > /dev/null; then
487 # limit our resource usage
488 ulimit -t $MAXTIME 2> /dev/null
491 ulimit -m $MAXMEM 2> /dev/null
494 # darn, this affects sparse files too! disable it
495 # ulimit -f 100000 2> /dev/null
497 # try and limit the number of open files to 150. That means we'll discover
499 ulimit -n 150 2> /dev/null
504 if [ -z "$test_root" ]; then
508 log="build.$tree.$host.$compiler.log"
509 err="build.$tree.$host.$compiler.err"
510 sum="build.$tree.$host.$compiler.sum"
511 lck="build.$tree.lck"
512 srcdir="$test_root/$tree/$source"
514 lock_file "$lck" || {
518 # work out what other trees this package depends on
522 deptrees="libreplace";
525 deptrees="libreplace talloc tdb";
532 # pull the svn entries, if any
533 if fetch_svn "$tree"; then
534 for d in $deptrees; do
535 if [ -f "$test_root/$d.svn" ]; then
536 if [ "$d" != "$tree" ]; then
537 cat "$test_root/$d.svn" >> $test_root/$tree.svn
541 rm -f $test_root/$tree.$compiler.svn.old
542 mv $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old
543 cp $test_root/$tree.svn $test_root/$tree.$compiler.svn
544 if cmp $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old > /dev/null; then
545 echo "skip: $tree.$compiler nothing changed in svn"
547 send_logs_skip "$log" "$err"
554 fetch_tree "$tree" || {
560 if [ ! -x $srcdir/configure ] && [ "$tree" != "pidl" ]; then
561 echo "skip: $tree.$compiler configure not present, try again next time!"
567 echo "Starting build of $tree.$compiler in process $$ at `date`"
570 tdb | talloc | ldb | libreplace)
571 builddir="$test_root/tmp.$tree.$compiler"
573 if [ -d $builddir ]; then
586 if [ ! x$USER = x"" ]; then
589 if [ ! x$LOGNAME = x"" ]; then
596 prefix="$test_root/prefix/$tree.$compiler"
599 s4selftest=$test_root/s4selftest
605 samba4|lorikeet-heimdal)
606 sw_config="$config --enable-socket-wrapper"
609 sw_config="$config --enable-socket-wrapper"
610 s4selftest_update "$tree" "$compiler" && {
611 t="$s4selftest.$tree.$compiler/source"
612 sw_config="$sw_config --with-samba4srcdir=$t"
616 PKG_CONFIG_PATH="$test_root/prefix/samba4.$compiler/lib/pkgconfig"
617 export PKG_CONFIG_PATH
623 fetch_tree libreplace
630 if [ "$LCOV_REPORT" = "yes" ]; then
631 GCOV_FLAGS="-ftest-coverage -fprofile-arcs"
633 HOSTCC_CFLAGS="$HOSTCC_CFLAGS $GCOV_FLAGS"
634 CFLAGS="$CFLAGS $GCOV_FLAGS"
635 LDFLAGS="$LDFLAGS $GCOV_FLAGS $GCOV_LIBS"
636 SHLD_FLAGS="$SHLD_FLAGS $GCOV_FLAGS $GCOV_LIBS"
637 export HOSTCC_CFLAGS CFLAGS LDFLAGS SHLD_FLAGS
640 config_and_prefix="$sw_config --prefix=$prefix"
642 # see if we need to rebuild
643 sum_tree $test_root $tree $sum
644 echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
646 if cmp "$sum" "$sum.old" > /dev/null; then
647 echo "skip: $tree.$compiler nothing changed"
649 send_logs_skip "$log" "$err"
651 echo "Ending build of $tree.$compiler in process $$ at `date`"
655 # we do need to rebuild - save the old sum
661 if [ "$actions" = "" ]; then
662 actions="configure config_log build install test"
667 # we all want to be able to read the output...
674 echo "build_test : $build_test_id"
675 echo "build_test.fns : $build_test_fns_id"
676 echo "local settings file : $build_test_settings_local_file"
677 echo "local functions file: $build_test_fns_local_file"
678 echo "used .fns file : $build_test_used_fns_file"
681 # we need to be able to see if a build farm machine is accumulating
682 # stuck processes. We do this in two ways, as we don't know what style
685 ps -fu $USER 2> /dev/null
687 echo "building $tree with CC=$compiler on $host at "`date`
688 echo "builddir=$builddir"
689 echo "prefix=$prefix"
691 echo "Showing limits"
692 ulimit -a 2> /dev/null
694 # build the timelimit utility
695 echo "Building timelimit"
697 $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
699 if [ -r $test_root/$tree.svn ]; then
700 h_rev=`grep revision= $test_root/$tree.svn | cut -d'"' -f2 | sort -n | tail -1`
701 if [ -n "$h_rev" ]; then
702 echo "HIGHEST SVN REVISION: $h_rev"
704 rev=`grep committed-rev= $test_root/$tree.svn | cut -d'"' -f2 | sort -n | tail -1`
705 if [ -n "$rev" ]; then
706 echo "BUILD REVISION: $rev"
711 if [ "$tree" = "pidl" ]
714 perl ./Makefile.PL "$prefix"
717 for action in $actions; do
719 echo Running action $action
723 cd $builddir || exit 1
732 if [ $action_status != 0 ]; then
733 echo "ACTION FAILED: $action";
735 echo "ACTION PASSED: $action";
738 if [ $action_status != 0 ]; then
744 if [ "$LCOV_REPORT" = "yes" ]; then
747 lcov --directory $builddir --capture --output-file $builddir/$tree.lcov.info
750 # ugly hack for s4, as lcov is otherwise not able to find
752 rm -f heimdal/lib/*/{lex,parse}.{gcda,gcno}
753 lcov --base-directory $builddir --directory $builddir --capture --output-file $builddir/$tree.lcov.info
756 genhtml -o $builddir/coverage $builddir/$tree.lcov.info
759 if [ "$noclean" = "yes" ]; then
760 echo cleanup skipped!
768 if [ "$LCOV_REPORT" = "yes" ]; then
769 chmod u=rwX,g=rX,o=rX -R $builddir/coverage
770 rsync -rct -q --password-file=.password -z --timeout=200 \
771 $builddir/coverage/ $host@build.samba.org::lcov_data/$host/$tree/
777 if [ "$usingtmpbuild" = "1" ]; then
778 if [ "$noclean" = "yes" ]; then
779 echo builddir cleanup skipped!
781 /bin/rm -rf $builddir
784 # send the logs to the master site
785 send_logs "$log" "$err"
788 echo "Ending build of $tree.$compiler in process $$ at `date`"
792 #########################################################
793 # if you want to build only one project at a time
794 # add 'global_lock' after 'per_run_hook' and
795 # 'global_unlock' to the end of the file
797 lock_file "global.lck" || {
802 unlock_file "global.lck"
805 #########################################################
806 # enable this on a per host basis only when needed please
807 # (at least for the moment)
808 kill_old_processes() {
809 # this should work on systems with linux like ps
810 (ps uxfw | grep /build | grep -v grep | egrep 'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec' | awk '{print $2}' | xargs kill -9) 2> /dev/null
811 # and this should work on sysv style ps
812 (ps -fu $USER | grep /build | grep -v grep | egrep 'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec' | awk '{print $2}' | xargs kill -9) 2> /dev/null
816 # this is a special fn that allows us to add a "special" hook to the build
817 # farm that we want to do to the build farm. never leave it empty. instead,
818 # use ":" as the fn body.
820 # kill old processes on systems with a known problem
823 echo "just a placeholder";
832 # trim the log if too large
833 if [ "`wc -c < build.log`" -gt 2000000 ]; then
839 ######################################################
840 # main code that is run on each call to the build code
841 rsync --timeout=200 -q -az build.samba.org::build_farm/*.c .
844 # build.log can grow to an excessive size, trim it beyond 50M
845 if [ -f build.log ]; then
846 find build.log -size +100000 -exec /bin/rm '{}' \;