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
28 find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v version.h | sort | xargs sum > $sum_tree_sum
29 sum build_test build_test.fns >> $sum_tree_sum
31 if [ -f "$host.fns" ]; then
32 sum $host.fns >> $sum_tree_sum
34 sum generic.fns >> $sum_tree_sum
37 if [ -f "$test_root/$tree.$scm" ]; then
38 sum "$test_root/$tree.$scm" >> $sum_tree_sum
41 for d in $deptrees; do
42 dscm=`choose_scm "$d"`
43 if [ -f "$test_root/$d.$dscm" ]; then
44 sum "$test_root/$d.$dscm" >> $sum_tree_sum
49 #############################
50 # send the logs to the master site
52 if [ "$nologreturn" = "yes" ]; then
53 echo "skipping log transfer"
59 chmod 0644 "$log" "$err"
62 if [ "`uname`" = "FreeBSD" ]; then
63 XARGS_I="xargs -I '{}' -R -1"
65 if [ "`uname`" = "Darwin" ]; then
66 XARGS_I="xargs -I '{}' -R -1"
68 find $log -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
69 find $err -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
71 rsync $* -ct -q --password-file=.password -z --timeout=200 \
72 "$log" "$err" $host@build.samba.org::build_farm_data/
76 #############################
77 # send the logs when they haven't changed
78 # the aim is to just update the servers timestamp.
79 # sending with a very large rsync block size does this
80 # with minimal network traffic
83 send_logs "$1" "$2" -B 10000000
86 ############################
87 # fetch the latest copy of the tree
89 if [ "$norsync" = "yes" ]; then
90 echo "skipping tree transfer"
93 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --delete-excluded -q --partial --timeout=200 -crlpz --delete --ignore-errors \
94 samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
95 echo "transferred $fetchtree OK"
97 echo "transfer of $fetchtree failed code $?"
104 ############################
105 # fetch the latest copy of the rev meta info
110 test -z "$scm" && return 1
111 test x"$scm" = x"unknown" && return 1
112 test x"$scm" = x"cvs" && return 1
114 if [ "$norsync" = "yes" ]; then
115 echo "skipping .revinfo.$scm transfer"
117 if [ -r $test_root/$tree.$scm ]; then
118 rm -f $test_root/$tree.$scm.old
119 mv $test_root/$tree.$scm $test_root/$tree.$scm.old
121 rsync -q --timeout=200 -clz --ignore-errors \
122 samba.org::ftp/unpacked/$tree/.revinfo.$scm $test_root/$tree.$scm
124 if [ -r $test_root/$tree.$scm ]; then
130 ############################
131 # choose the scm that is used for the given project
136 ccache | distcc | rsync)
148 ############################
149 # grab a lock file. Not atomic, but close :)
150 # tries to cope with NFS
152 if [ -z "$lock_root" ]; then
156 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
157 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
159 if [ "$pid" = "$$" ]; then
160 locknesting=`expr $locknesting + 1`
161 echo "lock nesting now $locknesting"
165 if test -f "$lckf"; then
166 test $machine = $host || {
167 echo "lock file $lckf is valid for other machine $machine"
171 echo "lock file $lckf is valid for process $pid"
174 echo "stale lock file $lckf for $machine:$pid"
178 echo "$host:$$" > "$lckf"
182 ############################
185 if [ -z "$lock_root" ]; then
188 if [ "$locknesting" != "0" ]; then
189 locknesting=`expr $locknesting - 1`
190 echo "lock nesting now $locknesting"
197 ############################
198 # run make, and print trace
207 # some trees don't need as much time
209 rsync | tdb | talloc | libreplace | ccache | distcc)
210 if [ "$compiler" != "checker" ]; then
211 MMTIME=`expr $MMTIME / 5`
218 if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
220 ./timelimit $MMTIME "$MAKE" "$t"
223 # we can parallelize everything and all targets
224 if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
225 echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
226 ./timelimit $MMTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
230 ./timelimit $MMTIME "$MAKE" "$t"
235 if [ $status != 0 ]; then
244 ############################
247 if [ ! -x $srcdir/configure ]; then
248 ls -l $srcdir/configure
249 echo "$srcdir/configure is missing"
251 echo "CONFIGURE STATUS: $cstatus"
254 echo "CFLAGS=$CFLAGS"
255 echo configure options: $config_and_prefix
256 echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
257 CC="$CCACHE $compiler"
259 ./timelimit $MAXTIME $srcdir/configure $config_and_prefix
261 echo "CONFIGURE STATUS: $cstatus"
262 if [ -f config.h ]; then
263 echo "contents of config.h:"
266 if [ -f include/config.h ]; then
267 echo "contents of include/config.h:"
273 ############################
274 # show the configure log
275 action_config_log() {
276 if [ ! -f config.log ]; then
279 echo "contents of config.log:"
287 rsync -a --delete $Tsrc/ $Tdst
290 s4selftest_create() {
291 lock_file "s4selftest.lck" || {
296 mkdir -p $s4selftest/source
298 copy_dir $builddir/bin $s4selftest/source/bin || {
300 unlock_file "s4selftest.lck";
304 copy_dir $srcdir/setup $s4selftest/source/setup || {
306 unlock_file "s4selftest.lck";
310 copy_dir $srcdir/../testprogs $s4selftest/testprogs || {
312 unlock_file "s4selftest.lck";
316 copy_dir $srcdir/selftest $s4selftest/source/selftest || {
318 unlock_file "s4selftest.lck";
322 copy_dir $srcdir/script $s4selftest/source/script || {
324 unlock_file "s4selftest.lck";
328 mkdir -p $s4selftest/source/scripting || {
330 unlock_file "s4selftest.lck";
334 copy_dir $srcdir/scripting/libjs $s4selftest/source/scripting/libjs || {
336 unlock_file "s4selftest.lck";
340 unlock_file "s4selftest.lck"
343 s4selftest_update() {
344 lock_file "s4selftest.lck" || {
348 copy_dir $s4selftest $s4selftest.$tree.$compiler.$$ || {
349 rm -rf $s4selftest.$tree.$compiler.$$;
350 unlock_file "s4selftest.lck";
354 rm -rf $s4selftest.$tree.$compiler
355 mv $s4selftest.$tree.$compiler.$$ $s4selftest.$tree.$compiler
357 unlock_file "s4selftest.lck"
360 ############################
367 if test x"$bstatus" != x"0"; then
368 # the 2nd 'make everything' is to work around a bug
374 if test x"$bstatus" != x"0"; then
379 if test x"$bstatus" = x"0"; then
385 do_make proto everything torture
394 echo "BUILD STATUS: $bstatus"
399 ############################
400 # show static analysis results
401 action_cc_checker() {
403 # default to passing the cc_checker
406 if [ -f ibm_checker.out ]; then
408 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
411 echo "CC_CHECKER STATUS: $cccstatus"
415 ############################
418 if [ -d $prefix ]; then
419 if [ "$noclean" != "yes" ]; then
426 echo "INSTALL STATUS: $istatus"
430 ############################
432 action_test_samba() {
435 return "$totalstatus"
438 action_test_generic() {
443 echo "TEST STATUS: $totalstatus"
444 return "$totalstatus"
447 action_test_lorikeet_heimdal() {
450 SOCKET_WRAPPER_DIR=`pwd`/sw
451 mkdir $SOCKET_WRAPPER_DIR
452 export SOCKET_WRAPPER_DIR
456 export SOCKET_WRAPPER_DIR
457 echo "TEST STATUS: $totalstatus"
458 return "$totalstatus"
462 #############################
463 # attempt some basic tests of functionaility
464 # starting as basic as possible, and getting incresingly complex
467 # Samba needs crufty code of its own for backward
468 # compatiblity. I think a better way to do this in the future
469 # is to just call 'make installcheck'.
472 # echo "testing of samba_3* disabled until cause of runaway processes found (tridge - 7th sep 2006)"
474 samba*|smb-build|pidl)
478 action_test_lorikeet_heimdal
486 ###########################
487 # do a test build of a particular tree
495 if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && ccache -V > /dev/null; then
502 # limit our resource usage
503 ulimit -t $MAXTIME 2> /dev/null
506 ulimit -m $MAXMEM 2> /dev/null
509 # darn, this affects sparse files too! disable it
510 # ulimit -f 100000 2> /dev/null
512 # try and limit the number of open files to 150. That means we'll discover
514 ulimit -n 150 2> /dev/null
519 if [ -z "$test_root" ]; then
523 log="build.$tree.$host.$compiler.log"
524 err="build.$tree.$host.$compiler.err"
525 sum="build.$tree.$host.$compiler.sum"
526 lck="build.$tree.lck"
527 srcdir="$test_root/$tree/$source"
529 lock_file "$lck" || {
533 # work out what other trees this package depends on
537 deptrees="libreplace";
540 deptrees="libreplace talloc tdb";
547 scm=`choose_scm "$tree"`
549 # pull the entries, if any
550 if fetch_revinfo "$tree" "$scm"; then
551 for d in $deptrees; do
552 dscm=`choose_scm "$d"`
553 if [ -f "$test_root/$d.$dscm" ]; then
554 if [ "$d" != "$tree" ]; then
555 cat "$test_root/$d.$dscm" >> $test_root/$tree.$scm
559 rm -f $test_root/$tree.$compiler.$scm.old
560 mv $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old
561 cp $test_root/$tree.$scm $test_root/$tree.$compiler.$scm
562 if cmp $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old > /dev/null; then
563 echo "skip: $tree.$compiler nothing changed in $scm"
565 send_logs_skip "$log" "$err"
572 fetch_tree "$tree" || {
578 if [ ! -x $srcdir/configure ] && [ "$tree" != "pidl" ]; then
579 echo "skip: $tree.$compiler configure not present, try again next time!"
585 echo "Starting build of $tree.$compiler in process $$ at `date`"
588 tdb | talloc | ldb | libreplace)
589 builddir="$test_root/tmp.$tree.$compiler"
591 if [ -d $builddir ]; then
604 if [ ! x$USER = x"" ]; then
607 if [ ! x$LOGNAME = x"" ]; then
614 prefix="$test_root/prefix/$tree.$compiler"
617 s4selftest=$test_root/s4selftest
623 samba4|lorikeet-heimdal)
624 sw_config="$config --enable-socket-wrapper"
627 sw_config="$config --enable-socket-wrapper"
628 s4selftest_update "$tree" "$compiler" && {
629 t="$s4selftest.$tree.$compiler/source"
630 sw_config="$sw_config --with-samba4srcdir=$t"
634 PKG_CONFIG_PATH="$test_root/prefix/samba4.$compiler/lib/pkgconfig"
635 export PKG_CONFIG_PATH
641 fetch_tree libreplace
648 if [ "$LCOV_REPORT" = "yes" ]; then
649 GCOV_FLAGS="-ftest-coverage -fprofile-arcs"
651 HOSTCC_CFLAGS="$HOSTCC_CFLAGS $GCOV_FLAGS"
652 CFLAGS="$CFLAGS $GCOV_FLAGS"
653 LDFLAGS="$LDFLAGS $GCOV_FLAGS $GCOV_LIBS"
654 SHLD_FLAGS="$SHLD_FLAGS $GCOV_FLAGS $GCOV_LIBS"
655 export HOSTCC_CFLAGS CFLAGS LDFLAGS SHLD_FLAGS
658 config_and_prefix="$sw_config --prefix=$prefix"
660 # see if we need to rebuild
661 sum_tree $test_root $tree $sum $scm
662 echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
664 if cmp "$sum" "$sum.old" > /dev/null; then
665 echo "skip: $tree.$compiler nothing changed"
667 send_logs_skip "$log" "$err"
669 echo "Ending build of $tree.$compiler in process $$ at `date`"
673 # we do need to rebuild - save the old sum
679 if [ "$actions" = "" ]; then
680 actions="configure config_log build install test"
685 # we all want to be able to read the output...
692 echo "build_test : $build_test_id"
693 echo "build_test.fns : $build_test_fns_id"
694 echo "local settings file : $build_test_settings_local_file"
695 echo "local functions file: $build_test_fns_local_file"
696 echo "used .fns file : $build_test_used_fns_file"
699 # we need to be able to see if a build farm machine is accumulating
700 # stuck processes. We do this in two ways, as we don't know what style
703 ps -fu $USER 2> /dev/null
705 echo "building $tree with CC=$compiler on $host at "`date`
706 echo "builddir=$builddir"
707 echo "prefix=$prefix"
709 echo "Showing limits"
710 ulimit -a 2> /dev/null
712 # build the timelimit utility
713 echo "Building timelimit"
715 $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
717 # the following is for non-samba builds only
718 if [ -r $test_root/$tree.svn ]; then
719 h_rev=`grep 'Revision: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
720 if [ -n "$h_rev" ]; then
721 echo "HIGHEST SVN REVISION: $h_rev"
723 rev=`grep 'Last Changed Rev: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
724 if [ -n "$rev" ]; then
725 echo "BUILD REVISION: $rev"
730 if [ "$tree" = "pidl" ]
733 perl ./Makefile.PL "$prefix"
736 for action in $actions; do
738 echo Running action $action
742 cd $builddir || exit 1
751 if [ $action_status != 0 ]; then
752 echo "ACTION FAILED: $action";
754 echo "ACTION PASSED: $action";
757 if [ $action_status != 0 ]; then
763 if [ "$LCOV_REPORT" = "yes" ]; then
766 lcov --directory $builddir --capture --output-file $builddir/$tree.lcov.info
769 # ugly hack for s4, as lcov is otherwise not able to find
771 rm -f heimdal/lib/*/{lex,parse}.{gcda,gcno}
772 lcov --base-directory $builddir --directory $builddir --capture --output-file $builddir/$tree.lcov.info
775 genhtml -o $builddir/coverage $builddir/$tree.lcov.info
778 if [ "$noclean" = "yes" ]; then
779 echo cleanup skipped!
787 if [ "$LCOV_REPORT" = "yes" ]; then
788 chmod u=rwX,g=rX,o=rX -R $builddir/coverage
789 rsync -rct -q --password-file=.password -z --timeout=200 \
790 $builddir/coverage/ $host@build.samba.org::lcov_data/$host/$tree/
796 if [ "$usingtmpbuild" = "1" ]; then
797 if [ "$noclean" = "yes" ]; then
798 echo builddir cleanup skipped!
800 /bin/rm -rf $builddir
803 # send the logs to the master site
804 send_logs "$log" "$err"
807 echo "Ending build of $tree.$compiler in process $$ at `date`"
811 #########################################################
812 # if you want to build only one project at a time
813 # add 'global_lock' after 'per_run_hook' and
814 # 'global_unlock' to the end of the file
816 lock_file "global.lck" || {
821 unlock_file "global.lck"
824 #########################################################
825 # enable this on a per host basis only when needed please
826 # (at least for the moment)
827 kill_old_processes() {
828 # this should work on systems with linux like ps
829 (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
830 # and this should work on sysv style ps
831 (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
835 # this is a special fn that allows us to add a "special" hook to the build
836 # farm that we want to do to the build farm. never leave it empty. instead,
837 # use ":" as the fn body.
839 # kill old processes on systems with a known problem
842 echo "just a placeholder";
851 # trim the log if too large
852 if [ "`wc -c < build.log`" -gt 2000000 ]; then
858 ######################################################
859 # main code that is run on each call to the build code
860 rsync --timeout=200 -q -az build.samba.org::build_farm/*.c .
863 # build.log can grow to an excessive size, trim it beyond 50M
864 if [ -f build.log ]; then
865 find build.log -size +100000 -exec /bin/rm '{}' \;