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"
61 # xargs -i is implemented differently or not at all.
62 # GNU xargs did not implement "-I" until 4.2.9:
63 xargs --version 2>&1 | grep "^GNU xargs" > /dev/null
65 if [ x"$status" = x"0" ]; then
69 if [ x"$XARGS_IS_GNU" = x"yes" ]; then
72 XARGS_I="xargs -I '{}'"
75 find $log -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
76 find $err -size +40000 | $XARGS_I sh -c 'dd if={} bs=1024 count=20000 of={}.tmp && mv {}.tmp {} && echo "\n***LOG TRUNCATED***" >> {}'
78 rsync $* -c -q --password-file=.password -z --timeout=200 \
79 "$log" "$err" $host@build.samba.org::build_farm_data/
83 #############################
84 # send the logs when they haven't changed
85 # the aim is to just update the servers timestamp.
86 # sending with a very large rsync block size does this
87 # with minimal network traffic
90 send_logs "$1" "$2" -B 10000000
93 ############################
94 # fetch the latest copy of the tree
96 if [ "$norsync" = "yes" ]; then
97 echo "skipping tree transfer"
100 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --exclude=.git/ \
101 --delete-excluded -q --partial --timeout=200 -ctrlpz --delete --ignore-errors \
102 samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
103 echo "transferred $fetchtree OK"
105 echo "transfer of $fetchtree failed code $?"
112 ############################
113 # fetch the latest copy of the rev meta info
118 test -z "$scm" && return 1
119 test x"$scm" = x"unknown" && return 1
120 test x"$scm" = x"cvs" && return 1
122 if [ "$norsync" = "yes" ]; then
123 echo "skipping .revinfo.$scm transfer"
125 if [ -r $test_root/$tree.$scm ]; then
126 rm -f $test_root/$tree.$scm.old
127 mv $test_root/$tree.$scm $test_root/$tree.$scm.old
129 rsync -q --timeout=200 -clz --ignore-errors \
130 samba.org::ftp/unpacked/$tree/.revinfo.$scm $test_root/$tree.$scm
132 if [ -r $test_root/$tree.$scm ]; then
138 ############################
139 # choose the scm that is used for the given project
144 samba* | rsync | libreplace | talloc | tdb | ldb | pidl | ccache*)
156 ############################
157 # grab a lock file. Not atomic, but close :)
158 # tries to cope with NFS
160 if [ -z "$lock_root" ]; then
164 machine=`cat "$lckf" 2> /dev/null | cut -d: -f1`
165 pid=`cat "$lckf" 2> /dev/null | cut -d: -f2`
167 if [ "$pid" = "$$" ]; then
168 locknesting=`expr $locknesting + 1`
169 echo "lock nesting now $locknesting"
173 if test -f "$lckf"; then
174 test $machine = $host || {
175 echo "lock file $lckf is valid for other machine $machine"
179 echo "lock file $lckf is valid for process $pid"
182 echo "stale lock file $lckf for $machine:$pid"
186 echo "$host:$$" > "$lckf"
190 ############################
193 if [ -z "$lock_root" ]; then
196 if [ "$locknesting" != "0" ]; then
197 locknesting=`expr $locknesting - 1`
198 echo "lock nesting now $locknesting"
205 ############################
206 # run make, and print trace
215 # some trees don't need as much time
217 rsync | tdb | talloc | libreplace | ccache*)
218 if [ "$compiler" != "checker" ]; then
219 MMTIME=`expr $MMTIME / 5`
226 if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
228 ./timelimit $MMTIME "$MAKE" "$t"
231 # we can parallelize everything and all targets
232 if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
233 echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
234 ./timelimit $MMTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS" "$t"
238 ./timelimit $MMTIME "$MAKE" "$t"
243 if [ $status != 0 ]; then
252 ############################
255 if [ ! -x $srcdir/configure -a -r $srcdir/Makefile.PL ]; then
256 perl $srcdir/Makefile.PL PREFIX="$prefix"
258 echo "CONFIGURE STATUS: $cstatus"
261 if [ ! -x $srcdir/configure ]; then
262 ls -l $srcdir/configure
263 echo "$srcdir/configure is missing"
265 echo "CONFIGURE STATUS: $cstatus"
268 echo "CFLAGS=$CFLAGS"
269 echo configure options: $config_and_prefix
270 echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
271 CC="$CCACHE $compiler"
273 ./timelimit $MAXTIME $srcdir/configure $config_and_prefix
275 if [ x"$cstatus" != x"0" ]; then
276 if [ -f config.log ]; then
277 echo "contents of config.log:"
280 if [ -f bin/config.log ]; then
281 echo "contents of config.log:"
285 echo "CONFIGURE STATUS: $cstatus"
289 ############################
290 # show the configure log
291 action_config_log() {
292 log_files="config.log bin/config.log"
293 for f in $log_files; do
295 echo "contents of config.log:"
303 ############################
305 action_config_header() {
306 hdr_files="config.h include/config.h bin/default/config.h bin/default/source4/include/config.h bin/default/source3/include/config.h"
307 for h in $hdr_files; do
309 echo "contents of $h:"
321 echo rsync -a --delete $Tsrc/ $Tdst
322 rsync -a --delete $Tsrc/ $Tdst || return 1
326 s4selftest_create() {
327 lock_file "s4selftest.lck" || {
328 echo "s4selftest_create: already locked"
332 # we currently only need smbtorture
333 mkdir -p $s4selftest/source/bin
334 echo "s4selftest_create: rsync -aL $builddir/bin/smbtorture.static $s4selftest/source/bin/smbtorture"
335 rsync -aL $builddir/bin/smbtorture.static $s4selftest/source/bin/smbtorture || {
336 echo "s4selftest_create: failed rsync"
337 unlock_file "s4selftest.lck";
341 unlock_file "s4selftest.lck"
342 echo "s4selftest_create: OK"
345 copy_dir $builddir/bin $s4selftest/source/bin || {
347 unlock_file "s4selftest.lck";
351 copy_dir $srcdir/setup $s4selftest/source/setup || {
353 unlock_file "s4selftest.lck";
357 copy_dir $srcdir/../testprogs $s4selftest/testprogs || {
359 unlock_file "s4selftest.lck";
363 copy_dir $srcdir/selftest $s4selftest/source/selftest || {
365 unlock_file "s4selftest.lck";
369 copy_dir $srcdir/script $s4selftest/source/script || {
371 unlock_file "s4selftest.lck";
375 mkdir -p $s4selftest/source/scripting || {
377 unlock_file "s4selftest.lck";
381 unlock_file "s4selftest.lck"
384 s4selftest_update() {
385 lock_file "s4selftest.lck" || {
386 echo "s4selftest_update LOCKED"
390 echo tmp.$tree.$compiler.$$ >tmp.dirname
391 tempdir=`cut -b1-32 tmp.dirname`
394 echo "COPYING $s4selftest => $tempdir"
395 copy_dir $s4selftest $tempdir || {
397 unlock_file "s4selftest.lck";
398 echo "s4selftest_update COPY FAILED"
402 echo "RENAMING $tempdir $s4selftest.$tree.$compiler"
403 rm -rf $s4selftest.$tree.$compiler
404 mv $tempdir $s4selftest.$tree.$compiler
406 unlock_file "s4selftest.lck"
407 echo "s4selftest_update OK"
411 ############################
418 if test x"$bstatus" != x"0"; then
419 # the 2nd 'make everything' is to work around a bug
425 if test x"$bstatus" != x"0"; then
430 if test x"$bstatus" = x"0"; then
436 do_make everything torture
445 echo "BUILD STATUS: $bstatus"
450 ############################
451 # show static analysis results
452 action_cc_checker() {
454 # default to passing the cc_checker
457 if [ -f ibm_checker.out ]; then
459 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
462 echo "CC_CHECKER STATUS: $cccstatus"
466 ############################
469 if [ -d $prefix ]; then
470 if [ "$noclean" != "yes" ]; then
477 echo "INSTALL STATUS: $istatus"
481 ############################
483 action_test_samba() {
486 # if we produced a test summary then show it
487 [ -f st/summary ] && {
491 return "$totalstatus"
494 action_test_generic() {
499 echo "TEST STATUS: $totalstatus"
500 return "$totalstatus"
503 action_test_lorikeet_heimdal() {
506 SOCKET_WRAPPER_DIR=`pwd`/sw
507 mkdir $SOCKET_WRAPPER_DIR
508 export SOCKET_WRAPPER_DIR
512 export SOCKET_WRAPPER_DIR
513 echo "TEST STATUS: $totalstatus"
514 return "$totalstatus"
518 #############################
519 # attempt some basic tests of functionaility
520 # starting as basic as possible, and getting incresingly complex
523 # Samba needs crufty code of its own for backward
524 # compatiblity. I think a better way to do this in the future
525 # is to just call 'make installcheck'.
527 samba*|smb-build|pidl)
531 action_test_lorikeet_heimdal
539 ###########################
540 # do a test build of a particular tree
548 if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && [ "$tree" != "ccache-maint" ] && ccache -V > /dev/null; then
555 # limit our resource usage
556 ulimit -t $MAXTIME 2> /dev/null
559 ulimit -m $MAXMEM 2> /dev/null
562 # darn, this affects sparse files too! disable it
563 # ulimit -f 100000 2> /dev/null
565 # try and limit the number of open files to 250. That means we'll discover
567 ulimit -n 250 2> /dev/null
572 if [ -z "$test_root" ]; then
576 log="build.$tree.$host.$compiler.log"
577 err="build.$tree.$host.$compiler.err"
578 sum="build.$tree.$host.$compiler.sum"
579 lck="build.$tree.lck"
580 srcdir="$test_root/$tree/$source"
582 lock_file "$lck" || {
586 # work out what other trees this package depends on
590 deptrees="samba_4_0_test"
594 scm=`choose_scm "$tree"`
596 # pull the entries, if any
597 if fetch_revinfo "$tree" "$scm"; then
598 for d in $deptrees; do
599 dscm=`choose_scm "$d"`
600 if [ -f "$test_root/$d.$dscm" ]; then
601 if [ "$d" != "$tree" ]; then
602 cat "$test_root/$d.$dscm" >> $test_root/$tree.$scm
606 rm -f $test_root/$tree.$compiler.$scm.old
607 mv $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old
608 cp $test_root/$tree.$scm $test_root/$tree.$compiler.$scm
609 if cmp $test_root/$tree.$compiler.$scm $test_root/$tree.$compiler.$scm.old > /dev/null; then
610 echo "skip: $tree.$compiler nothing changed in $scm"
612 send_logs_skip "$log" "$err"
619 fetch_tree "$tree" || {
625 if [ ! -x $srcdir/configure ] && [ "$tree" != "pidl" ]; then
626 echo "skip: $tree.$compiler configure not present, try again next time!"
632 echo "Starting build of $tree.$compiler in process $$ at `date`"
636 builddir="$test_root/tmp.$tree.$compiler"
638 if [ -d $builddir ]; then
651 if [ ! x$USER = x"" ]; then
654 if [ ! x$LOGNAME = x"" ]; then
661 prefix="$test_root/prefix/$tree.$compiler"
664 s4selftest=$test_root/s4selftest
671 sw_config="$config --enable-socket-wrapper"
674 sw_config="$config --enable-socket-wrapper"
675 sw_config="$sw_config --enable-nss-wrapper"
676 sw_config="$sw_config --enable-uid-wrapper"
679 sw_config="$config --enable-socket-wrapper"
680 sw_config="$sw_config --enable-nss-wrapper"
681 s4selftest_update "$tree" "$compiler" && {
682 t="$s4selftest.$tree.$compiler/source"
683 #sw_config="$sw_config --with-samba4srcdir=$t"
684 t="$t/bin/smbtorture"
685 sw_config="$sw_config --with-smbtorture4-path=$t"
689 PKG_CONFIG_PATH="$test_root/prefix/samba_4_0_test.$compiler/lib/pkgconfig"
690 export PKG_CONFIG_PATH
697 if [ "$LCOV_REPORT" = "yes" ]; then
698 GCOV_FLAGS="--coverage"
699 CFLAGS="$CFLAGS $GCOV_FLAGS"
700 LDFLAGS="$LDFLAGS $GCOV_FLAGS"
701 export CFLAGS LDFLAGS
704 config_and_prefix="$sw_config --prefix=$prefix"
706 # see if we need to rebuild
707 sum_tree $test_root $tree $sum $scm
708 echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
710 if cmp "$sum" "$sum.old" > /dev/null; then
711 echo "skip: $tree.$compiler nothing changed"
713 send_logs_skip "$log" "$err"
715 echo "Ending build of $tree.$compiler in process $$ at `date`"
719 # we do need to rebuild - save the old sum
725 if [ "$actions" = "" ]; then
726 actions="configure config_log config_header build install test"
732 # we all want to be able to read the output...
739 echo "build_test : $build_test_id"
740 echo "build_test.fns : $build_test_fns_id"
741 echo "local settings file : $build_test_settings_local_file"
742 echo "local functions file: $build_test_fns_local_file"
743 echo "used .fns file : $build_test_used_fns_file"
746 # we need to be able to see if a build farm machine is accumulating
747 # stuck processes. We do this in two ways, as we don't know what style
750 ps -fu $USER 2> /dev/null
752 echo "building $tree with CC=$compiler on $host at "`date`
753 echo "builddir=$builddir"
754 echo "prefix=$prefix"
756 echo "Showing limits"
757 ulimit -a 2> /dev/null
759 # the following is for non-samba builds only
760 if [ "$scm" = "svn" -a -r $test_root/$tree.svn ]; then
761 h_rev=`grep 'Revision: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
762 if [ -n "$h_rev" ]; then
763 echo "HIGHEST SVN REVISION: $h_rev"
765 rev=`grep 'Last Changed Rev: ' $test_root/$tree.svn | cut -d ':' -f2 | cut -d ' ' -f2 | sed 1q`
766 if [ -n "$rev" ]; then
767 echo "BUILD REVISION: $rev"
769 elif [ "$scm" = "git" -a -r $test_root/$tree.git ]; then
770 csha1=`cat $test_root/$tree.git |head -3 | tail -1`
771 if [ -n "$csha1" ]; then
772 echo "BUILD COMMIT REVISION: $csha1"
774 cdate=`cat $test_root/$tree.git |head -4 | tail -1`
775 if [ -n "$cdate" ]; then
776 echo "BUILD COMMIT DATE: $cdate"
778 ctime=`cat $test_root/$tree.git |head -2 | tail -1`
779 if [ -n "$ctime" ]; then
780 echo "BUILD COMMIT TIME: $ctime"
784 if [ -x $test_root/killbysubdir ]; then
785 $test_root/killbysubdir $builddir
788 for action in $actions; do
790 echo Running action $action
794 cd $builddir || exit 1
805 if [ $action_status != 0 ]; then
806 echo "ACTION FAILED: $action";
808 echo "ACTION PASSED: $action";
811 if [ $action_status != 0 ]; then
817 if [ "$LCOV_REPORT" = "yes" ]; then
820 lcov --directory $builddir --capture --output-file $builddir/$tree.lcov.info
823 lcov --base-directory $builddir --directory $builddir/.. --capture --output-file $builddir/$tree.lcov.info
826 # ugly hack for s4, as lcov is otherwise not able to find
828 rm -f heimdal/lib/*/{lex,parse,sel-lex}.{gcda,gcno}
829 lcov --base-directory $builddir --directory $builddir/.. --capture --output-file $builddir/$tree.lcov.info
832 lcov --base-directory $builddir --directory $builddir --capture --output-file $builddir/$tree.lcov.info
835 genhtml -o $builddir/coverage $builddir/$tree.lcov.info
838 if [ "$noclean" = "yes" ]; then
839 echo cleanup skipped!
845 } 3>&2 2>&1 1>&3 | tee "$err"
847 # be aware the above channel swap may sometimes result in unordered
848 # stdout/stderr merge
850 if [ "$LCOV_REPORT" = "yes" ]; then
851 chmod u=rwX,g=rX,o=rX -R $builddir/coverage
852 rsync -rct -q --password-file=.password -z --timeout=200 \
853 $builddir/coverage/ $host@build.samba.org::lcov_data/$host/$tree/
859 if [ "$usingtmpbuild" = "1" ]; then
860 if [ "$noclean" = "yes" ]; then
861 echo builddir cleanup skipped!
863 /bin/rm -rf $builddir
866 # send the logs to the master site
867 send_logs "$log" "$err"
870 echo "Ending build of $tree.$compiler in process $$ at `date`"
874 #########################################################
875 # if you want to build only one project at a time
876 # add 'global_lock' after 'per_run_hook' and
877 # 'global_unlock' to the end of the file
879 lock_file "global.lck" || {
884 unlock_file "global.lck"
890 test -z "$otree" && return 0;
897 rm -rf s4selftest.$otree.*
898 rm -rf build.$otree.*
901 # this is a special fn that allows us to add a "special" hook to the build
902 # farm that we want to do to the build farm. never leave it empty. instead,
903 # use ":" as the fn body.
905 # build the timelimit utility
906 echo "Building timelimit"
908 $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
910 # build the killbysubdir utility
911 echo "Building killbysubdir"
912 $compiler -o $test_root/killbysubdir $test_root/killbysubdir.c
914 # kill old processes on systems with a known problem
917 echo "just a placeholder";
923 # trim the log if too large
924 if [ "`wc -c < build.log`" -gt 2000000 ]; then
928 delete_old_tree "samba_3_2"
929 delete_old_tree "samba_3_2_test"
930 delete_old_tree "samba4"
931 delete_old_tree "samba_4_0_test"
932 delete_old_tree "samba_3_X_test"
933 delete_old_tree "samba_3_X_devel"
937 ######################################################
938 # main code that is run on each call to the build code
939 rsync --timeout=200 -q -az build.samba.org::build_farm/*.c .
942 # build.log can grow to an excessive size, trim it beyond 50M
943 if [ -f build.log ]; then
944 find build.log -size +100000 -exec /bin/rm '{}' \;