1 # -*- 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 RUN_FROM_BUILD_FARM=yes
12 export RUN_FROM_BUILD_FARM
16 build_test_fns_id='$Id$'
18 #############################
19 # build a signature of a tree, used to see if we
25 find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v '.svn' | grep -v version.h | sort | xargs sum > $sum_tree_sum
26 sum build_test build_test.fns >> $sum_tree_sum
28 if [ -f "$host.fns" ]; then
29 sum $host.fns >> $sum_tree_sum
31 sum generic.fns >> $sum_tree_sum
33 if [ -f "$test_root/$tree.svn" ]; then
34 sum "$test_root/$tree.svn" >> $sum_tree_sum
36 for d in $deptrees; do
37 if [ -f "$test_root/$d.svn" ]; then
38 sum "$test_root/$d.svn" >> $sum_tree_sum
43 #############################
44 # send the logs to the master site
46 if [ "$nologreturn" = "yes" ]; then
47 echo "skipping log transfer"
53 chmod 0644 "$log" "$err"
56 if [ "`uname`" = "FreeBSD" ]; then
57 XARGS_I="xargs -I '{}' -R -1"
59 find $log -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
60 find $err -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
62 rsync $* -ct -q --password-file=.password -z --timeout=200 \
63 "$log" "$err" $host@samba.org::build_farm_data/
67 #############################
68 # send the logs when they haven't changed
69 # the aim is to just update the servers timestamp.
70 # sending with a very large rsync block size does this
71 # with minimal network traffic
74 send_logs "$1" "$2" -B 10000000
77 ############################
78 # fetch the latest copy of the tree
80 if [ "$norsync" = "yes" ]; then
81 echo "skipping tree transfer"
84 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --delete-excluded -q --partial --timeout=200 -crlpz --delete --ignore-errors \
85 samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
86 echo "transferred $fetchtree OK"
88 echo "transfer of $fetchtree failed code $?"
95 ############################
96 # fetch the latest copy of the svn entries file
99 # skip products still in CVS.
101 ccache | distcc | rsync)
107 if [ "$norsync" = "yes" ]; then
108 echo "skipping svn transfer"
110 if [ -r $test_root/$tree.svn ]; then
111 rm -f $test_root/$tree.svn.old
112 mv $test_root/$tree.svn $test_root/$tree.svn.old
114 rsync -q --timeout=200 -clz --ignore-errors \
115 samba.org::ftp/unpacked/$tree/.svn/entries $test_root/$tree.svn.tmp
116 chmod u+w $test_root/$tree.svn.tmp
117 sort -u < $test_root/$tree.svn.tmp > $test_root/$tree.svn
118 rm -f $test_root/$tree.svn.tmp
120 if [ -r $test_root/$tree.svn ]; then
128 ############################
129 # grab a lock file. Not atomic, but close :)
130 # tries to cope with NFS
132 if [ -z "$lock_root" ]; then
136 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
137 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
139 if [ "$pid" = "$$" ]; then
140 locknesting=`expr $locknesting + 1`
141 echo "lock nesting now $locknesting"
145 if test -f "$lckf"; then
146 test $machine = $host || {
147 echo "lock file $lckf is valid for other machine $machine"
151 echo "lock file $lckf is valid for process $pid"
154 echo "stale lock file $lckf for $machine:$pid"
158 echo "$host:$$" > "$lckf"
162 ############################
165 if [ -z "$lock_root" ]; then
168 if [ "$locknesting" != "0" ]; then
169 locknesting=`expr $locknesting - 1`
170 echo "lock nesting now $locknesting"
177 ############################
178 # run make, and print trace
187 # some trees don't need as much time
189 rsync | tdb | talloc | libreplace | ccache | distcc)
190 if [ "$compiler" != "checker" ]; then
191 MMTIME=`expr $MMTIME / 5`
198 if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
200 ./timelimit $MMTIME "$MAKE" "$t"
203 # we can parallelize everything and all targets
204 if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
205 echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
206 ./timelimit $MMTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
210 ./timelimit $MMTIME "$MAKE" "$t"
215 if [ $status != 0 ]; then
224 ############################
227 if [ ! -x $srcdir/configure ]; then
228 ls -l $srcdir/configure
229 echo "$srcdir/configure is missing"
231 echo "CONFIGURE STATUS: $cstatus"
234 echo "CFLAGS=$CFLAGS"
235 echo configure options: $config_and_prefix
236 echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
237 CC="$CCACHE $compiler"
239 ./timelimit $MAXTIME $srcdir/configure $config_and_prefix
241 echo "CONFIGURE STATUS: $cstatus"
242 if [ -f config.h ]; then
243 echo "contents of config.h:"
246 if [ -f include/config.h ]; then
247 echo "contents of include/config.h:"
253 ############################
254 # show the configure log
255 action_config_log() {
256 if [ ! -f config.log ]; then
259 echo "contents of config.log:"
264 ############################
272 if test x"$bstatus" != x"0"; then
273 # the 2nd 'make everything' is to work around a bug
279 if [ -n "$smbtorture4" ]; then
280 if [ ! -f bin/smbtorture ]; then
281 do_make bin/smbtorture
283 if [ -f bin/smbtorture ]; then
284 cp bin/smbtorture $smbtorture4
290 do_make proto everything torture
299 echo "BUILD STATUS: $bstatus"
304 ############################
305 # show static analysis results
306 action_cc_checker() {
308 # default to passing the cc_checker
311 if [ -f ibm_checker.out ]; then
313 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
316 echo "CC_CHECKER STATUS: $cccstatus"
320 ############################
323 if [ -d $prefix ]; then
324 if [ "$noclean" != "yes" ]; then
331 echo "INSTALL STATUS: $istatus"
335 ############################
337 action_test_samba() {
340 return "$totalstatus"
343 action_test_generic() {
348 echo "TEST STATUS: $totalstatus"
349 return "$totalstatus"
352 action_test_lorikeet_heimdal() {
355 SOCKET_WRAPPER_DIR=`pwd`/sw
356 mkdir $SOCKET_WRAPPER_DIR
357 export SOCKET_WRAPPER_DIR
361 export SOCKET_WRAPPER_DIR
362 echo "TEST STATUS: $totalstatus"
363 return "$totalstatus"
367 #############################
368 # attempt some basic tests of functionaility
369 # starting as basic as possible, and getting incresingly complex
372 # Samba needs crufty code of its own for backward
373 # compatiblity. I think a better way to do this in the future
374 # is to just call 'make installcheck'.
377 # echo "testing of samba_3_0 disabled until cause of runaway processes found (tridge - 7th sep 2006)"
379 samba*|smb-build|pidl)
383 action_test_lorikeet_heimdal
391 ###########################
392 # do a test build of a particular tree
400 if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && ccache -V > /dev/null; then
407 # limit our resource usage
408 ulimit -t $MAXTIME 2> /dev/null
411 ulimit -m 100000 2> /dev/null
414 # darn, this affects sparse files too! disable it
415 # ulimit -f 100000 2> /dev/null
417 # try and limit the number of open files to 150. That means we'll discover
419 ulimit -n 150 2> /dev/null
424 if [ -z "$test_root" ]; then
428 log="build.$tree.$host.$compiler.log"
429 err="build.$tree.$host.$compiler.err"
430 sum="build.$tree.$host.$compiler.sum"
431 lck="build.$tree.lck"
432 srcdir="$test_root/$tree/$source"
434 lock_file "$lck" || {
438 # work out what other trees this package depends on
442 deptrees="libreplace";
445 deptrees="libreplace talloc tdb";
452 # pull the svn entries, if any
453 if fetch_svn "$tree"; then
454 for d in $deptrees; do
455 if [ -f "$test_root/$d.svn" ]; then
456 if [ "$d" != "$tree" ]; then
457 cat "$test_root/$d.svn" >> $test_root/$tree.svn
461 rm -f $test_root/$tree.$compiler.svn.old
462 mv $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old
463 cp $test_root/$tree.svn $test_root/$tree.$compiler.svn
464 if cmp $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old > /dev/null; then
465 echo "skip: $tree.$compiler nothing changed in svn"
467 send_logs_skip "$log" "$err"
474 fetch_tree "$tree" || {
480 if [ ! -x $srcdir/configure ] && [ "$tree" != "pidl" ]; then
481 echo "skip: $tree.$compiler configure not present, try again next time!"
487 echo "Starting build of $tree.$compiler in process $$ at `date`"
490 tdb | talloc | ldb | libreplace)
491 builddir="$test_root/tmp.$tree.$compiler"
493 if [ -d $builddir ]; then
506 if [ ! $USER = "" ]; then
509 if [ ! $LOGNAME = "" ]; then
516 prefix="$test_root/prefix/$tree.$compiler"
519 smbtorture4=$test_root/smbtorture4
525 samba4|lorikeet-heimdal)
526 sw_config="$config --enable-socket-wrapper"
529 sw_config="$config --enable-socket-wrapper"
530 if [ -f $smbtorture4 ]; then
531 # we create a local copy to make sure the same binary is used for all tests
532 cp $smbtorture4 $smbtorture4.$tree
533 sw_config="$sw_config --with-smbtorture4-path=$smbtorture4.$tree"
537 PKG_CONFIG_PATH="$test_root/prefix/samba4.$compiler/lib/pkgconfig"
538 export PKG_CONFIG_PATH
544 fetch_tree libreplace
551 if [ "$LCOV_REPORT" = "yes" ]; then
552 GCOV_FLAGS="-ftest-coverage -fprofile-arcs"
554 HOSTCC_CFLAGS="$HOSTCC_CFLAGS $GCOV_FLAGS"
555 CFLAGS="$CFLAGS $GCOV_FLAGS"
556 LDFLAGS="$LDFLAGS $GCOV_FLAGS $GCOV_LIBS"
557 SHLD_FLAGS="$SHLD_FLAGS $GCOV_FLAGS $GCOV_LIBS"
558 export HOSTCC_CFLAGS CFLAGS LDFLAGS SHLD_FLAGS
561 config_and_prefix="$sw_config --prefix=$prefix"
563 # see if we need to rebuild
564 sum_tree $test_root $tree $sum
565 echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
567 if cmp "$sum" "$sum.old" > /dev/null; then
568 echo "skip: $tree.$compiler nothing changed"
570 send_logs_skip "$log" "$err"
572 echo "Ending build of $tree.$compiler in process $$ at `date`"
576 # we do need to rebuild - save the old sum
582 if [ "$actions" = "" ]; then
583 actions="configure config_log build install test"
588 # we all want to be able to read the output...
593 echo $build_test_fns_id
594 echo $build_test_used_fns_file
598 # we need to be able to see if a build farm machine is accumulating
599 # stuck processes. We do this in two ways, as we don't know what style
602 ps -fu $USER 2> /dev/null
604 echo "building $tree with CC=$compiler on $host at "`date`
605 echo "builddir=$builddir"
606 echo "prefix=$prefix"
608 echo "Showing limits"
609 ulimit -a 2> /dev/null
611 # build the timelimit utility
612 echo "Building timelimit"
614 $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
616 if [ -r $test_root/$tree.svn ]; then
617 h_rev=`grep revision= $test_root/$tree.svn | cut -d'"' -f2 | sort -n | tail -1`
618 if [ -n "$h_rev" ]; then
619 echo "HIGHEST SVN REVISION: $h_rev"
621 rev=`grep committed-rev= $test_root/$tree.svn | cut -d'"' -f2 | sort -n | tail -1`
622 if [ -n "$rev" ]; then
623 echo "BUILD REVISION: $rev"
628 if [ "$tree" = "pidl" ]
631 perl ./Makefile.PL "$prefix"
634 for action in $actions; do
636 echo Running action $action
640 cd $builddir || exit 1
649 if [ $action_status != 0 ]; then
650 echo "ACTION FAILED: $action";
652 echo "ACTION PASSED: $action";
655 if [ $action_status != 0 ]; then
661 if [ "$LCOV_REPORT" = "yes" ]; then
664 lcov --directory $builddir --capture --output-file $builddir/$tree.lcov.info
667 # ugly hack for s4, as lcov is otherwise not able to find
669 rm -f heimdal/lib/*/{lex,parse}.{gcda,gcno}
670 lcov --base-directory $builddir --directory $builddir --capture --output-file $builddir/$tree.lcov.info
673 genhtml -o $builddir/coverage $builddir/$tree.lcov.info
676 if [ "$noclean" = "yes" ]; then
677 echo cleanup skipped!
685 if [ "$LCOV_REPORT" = "yes" ]; then
686 chmod u=rwX,g=rX,o=rX -R $builddir/coverage
687 rsync -rct -q --password-file=.password -z --timeout=200 \
688 $builddir/coverage/ $host@samba.org::lcov_data/$host/$tree/
694 if [ "$usingtmpbuild" = "1" ]; then
695 if [ "$noclean" = "yes" ]; then
696 echo builddir cleanup skipped!
698 /bin/rm -rf $builddir
701 # send the logs to the master site
702 send_logs "$log" "$err"
705 echo "Ending build of $tree.$compiler in process $$ at `date`"
709 #########################################################
710 # if you want to build only one project at a time
711 # add 'global_lock' after 'per_run_hook' and
712 # 'global_unlock' to the end of the file
714 lock_file "global.lck" || {
719 unlock_file "global.lck"
722 #########################################################
723 # enable this on a per host basis only when needed please
724 # (at least for the moment)
725 kill_old_processes() {
726 # this should work on systems with linux like ps
727 (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
728 # and this should work on sysv style ps
729 (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
733 # this is a special fn that allows us to add a "special" hook to the build
734 # farm that we want to do to the build farm. never leave it empty. instead,
735 # use ":" as the fn body.
737 # kill old processes on systems with a known problem
740 echo "just a placeholder";
749 # trim the log if too large
750 if [ "`wc -c < build.log`" -gt 2000000 ]; then
756 ######################################################
757 # main code that is run on each call to the build code
758 rsync --timeout=200 -q -az samba.org::build_farm/*.c .
761 # build.log can grow to an excessive size, trim it beyond 50M
762 if [ -f build.log ]; then
763 find build.log -size +100000 -exec /bin/rm '{}' \;