talloc needs libreplace downloaded
[build-farm.git] / build_test.fns
1 # -*- mode: shell-script; sh-indentation: 8; indent-tabs-mode: t; -*-
2
3 # build_farm -- distributed build/test architecture for samba, rsync, etc
4
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>
8
9 # default maximum runtime for any command
10 MAXTIME=7200
11 RUN_FROM_BUILD_FARM=yes
12 export RUN_FROM_BUILD_FARM
13
14 #############################
15 # build a signature of a tree, used to see if we
16 # need to rebuild 
17 sum_tree() {
18         sum_tree_test_root=$1
19         sum_tree_tree=$2
20         sum_tree_sum=$3
21         find $sum_tree_test_root/$sum_tree_tree -type f -print | grep -v '.svn' | grep -v version.h | sort | xargs sum > $sum_tree_sum
22         sum build_test build_test.fns >> $sum_tree_sum
23
24         if [ -f "$host.fns" ]; then
25             sum $host.fns >> $sum_tree_sum
26         else
27             sum generic.fns >> $sum_tree_sum
28         fi
29 }
30
31 #############################
32 # send the logs to the master site
33 send_logs() {
34         if [ "$nologreturn" = "yes" ]; then
35                 echo "skipping log transfer"
36         else
37                 log="$1"
38                 err="$2"
39                 chmod 0644 "$log" "$err"
40                 rsync -q --password-file=.password -cz --timeout=200 \
41                         "$log" "$err" $host@samba.org::build_farm_data/
42         fi
43 }
44
45 ############################
46 # fetch the latest copy of the tree
47 fetch_tree() {
48         if [ "$norsync" = "yes" ]; then
49                 echo "skipping tree transfer"
50         else
51                 fetchtree=$1
52                 if rsync --exclude=autom4te.cache/ --exclude=.svn/ --delete-excluded -q --partial --timeout=200 -crlpz --delete --ignore-errors \
53                         samba.org::ftp/unpacked/$fetchtree/ $test_root/$fetchtree; then
54                         echo "transferred $fetchtree OK"
55                 else
56                         echo "transfer of $fetchtree failed code $?"
57                         return 1
58                 fi
59         fi
60         return 0
61 }
62
63 ############################
64 # fetch the latest copy of the svn entries file
65 fetch_svn() {
66     tree=$1
67 # skip products still in CVS.
68     case "$tree" in
69     ccache | distcc | rsync)
70         return 1
71         ;;
72     *)
73         ;;
74     esac
75     if [ "$norsync" = "yes" ]; then
76         echo "skipping svn transfer"
77     else
78         if [ -r $test_root/$tree.svn ]; then
79                 rm -f $test_root/$tree.svn.old
80             mv $test_root/$tree.svn $test_root/$tree.svn.old
81         fi
82         rsync -q --timeout=200 -clz --ignore-errors \
83             samba.org::ftp/unpacked/$tree/.svn/entries $test_root/$tree.svn
84     fi
85     if [ -r $test_root/$tree.svn ]; then
86         return 0;
87     fi
88     return 1
89 }
90
91 ############################
92 # grab a lock file. Not atomic, but close :)
93 # tries to cope with NFS
94 lock_file() {
95         lck="$1"
96         machine=`cat "$lck" 2> /dev/null | cut -d: -f1`
97         pid=`cat "$lck" 2> /dev/null | cut -d: -f2`
98
99         if [ -f "$lck" ] && 
100             ( [ $machine != $host ] || kill -0 $pid ) 2> /dev/null; then
101                 echo "lock file $lck is valid for $machine:$pid"
102                 return 1
103         fi
104         /bin/rm -f "$lck"
105         echo "$host:$$" > "$lck"
106         return 0
107 }
108
109 ############################
110 # unlock a lock file
111 unlock_file() {
112         lck="$1"
113         /bin/rm -f "$lck"
114 }
115
116 ############################
117 # run make, and print trace
118 do_make() {
119
120   if [ x"$MAKE" = x ] 
121   then
122     MAKE=make
123   fi 
124     
125   for t in $*; do
126     if [ x"$BUILD_FARM_NUM_JOBS" = x ]; then
127       echo "$MAKE $t"
128       ./timelimit $MAXTIME "$MAKE" "$t"
129       status=$?
130     else
131       # we can parallelize everything and all targets
132       if [ x"$t" = xeverything ] || [ x"$t" = xall]; then
133         echo "$MAKE" "-j$BUILD_FARM_NUM_JOBS"  "$t"
134         ./timelimit $MAXTIME "$MAKE" "-j$BUILD_FARM_NUM_JOBS"  "$t"
135         status=$?
136       else
137         echo "$MAKE $t"
138         ./timelimit $MAXTIME "$MAKE" "$t"
139         status=$?
140       fi
141     fi
142
143     if [ $status != 0 ]; then
144       return $status;
145     fi
146
147   done
148
149   return 0
150 }      
151
152 ############################
153 # configure the tree
154 action_configure() {
155         if [ ! -x configure ]; then
156             ls -l configure
157             ./autogen.sh
158         fi
159         echo "CFLAGS=$CFLAGS"
160         echo configure options: $config_and_prefix
161         echo CC="$CCACHE $compiler" $srcdir/configure $config_and_prefix
162         CC="$CCACHE $compiler"
163         export CC
164         ./timelimit $MAXTIME $srcdir/configure $config_and_prefix
165         cstatus=$?
166         echo "CONFIGURE STATUS: $cstatus"
167         if [ $cstatus != 0 ]; then
168             echo "contents of config.log:"
169             cat config.log
170         fi
171         return $cstatus;
172 }
173
174 ############################
175 # build the tree
176 action_build() {
177         case "$tree" in
178         samba4)
179                 # the 2nd 'make everything' is to work around a bug
180                 # in netbsd make. 
181                 do_make proto showflags everything
182                 do_make everything
183                 do_make bin/smbtorture
184                 ;;
185         samba|samba_3_0)
186             do_make proto everything torture
187             ;;
188         *)
189             do_make all
190             ;;
191         esac
192
193         bstatus=$?
194         echo "BUILD STATUS: $bstatus"
195
196         if [ "$tree" = "samba4" ] && [ -n "$smbtorture4" ] && [ -f bin/smbtorture ]; then
197             rm -f $smbtorture4
198             cp bin/smbtorture $smbtorture4
199         fi
200         return $bstatus
201 }
202
203 ############################
204 # show static analysis results
205 action_cc_checker() {
206
207         # default to passing the cc_checker
208         cccstatus=0
209
210         if [ -f ibm_checker.out ]; then
211                 cat ibm_checker.out
212                 cccstatus=`cat ibm_checker.out | grep '^\-\- ' | wc -l`
213         fi
214
215         echo "CC_CHECKER STATUS: $cccstatus"
216         return $cccstatus;      
217 }
218
219 ############################
220 # install the tree
221 action_install() {
222         if [ -d $prefix ]; then
223                 if [ "$noclean" != "yes" ]; then
224                     rm -rf $prefix
225                 fi
226         fi
227
228         do_make install
229         istatus=$?
230         echo "INSTALL STATUS: $istatus"
231         return $istatus;
232 }
233
234 ############################
235 # test the tree
236 action_test_samba() {
237         do_make test
238         totalstatus=$?
239         return "$totalstatus"
240 }
241
242 action_test_generic() {
243         CC="$compiler"
244         export CC
245         do_make installcheck
246         totalstatus=$?
247         echo "TEST STATUS: $totalstatus"
248         return "$totalstatus"
249 }
250
251 action_test_lorikeet_heimdal() {
252         CC="$compiler"
253         export CC
254         do_make check
255         totalstatus=$?
256         echo "TEST STATUS: $totalstatus"
257         return "$totalstatus"
258 }
259
260
261 #############################
262 # attempt some basic tests of functionaility
263 # starting as basic as possible, and getting incresingly complex
264
265 action_test() {
266         # Samba needs crufty code of its own for backward
267         # compatiblity.  I think a better way to do this in the future
268         # is to just call 'make installcheck'.
269         case "$tree" in
270         samba*|smb-build)
271             action_test_samba
272             ;;
273         lorikeet-heimdal*)
274             action_test_lorikeet_heimdal
275             ;;
276         *)
277             action_test_generic
278             ;;
279         esac
280 }
281
282 ###########################
283 # do a test build of a particular tree
284 test_tree() {
285         tree=$1
286         source=$2
287         compiler="$3"
288         shift
289         shift
290         shift
291         if [ "$compiler" = "gcc" ] && [ "$tree" != "ccache" ] && ccache -V > /dev/null; then
292             CCACHE="ccache"
293             export CCACHE
294         else
295             CCACHE=""
296         fi
297
298         # limit our resource usage
299         ulimit -t $MAXTIME
300         ulimit -m 100000
301
302         # Keep stuff private
303         umask 077
304
305         if [ -z "$test_root" ]; then
306                 test_root=`pwd`
307         fi
308
309         log="build.$tree.$host.$compiler.log"
310         err="build.$tree.$host.$compiler.err"
311         sum="build.$tree.$host.$compiler.sum"
312         lck="$test_root/build.$tree.lck"
313         srcdir="$test_root/$tree/$source"
314
315         case "$tree" in
316             tdb | talloc | ldb | libreplace)
317                 builddir=$srcdir/tmpbuild
318                 export builddir
319             ;;
320             *)
321                 builddir=$srcdir
322                 export builddir
323             ;;
324         esac
325
326         if ! lock_file "$lck"; then
327                 return
328         fi
329
330         # pull the svn entries, if any
331         if fetch_svn "$tree"; then
332             rm -f $test_root/$tree.$compiler.svn.old
333             mv $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old
334             cp $test_root/$tree.svn $test_root/$tree.$compiler.svn
335             if cmp $test_root/$tree.$compiler.svn $test_root/$tree.$compiler.svn.old > /dev/null; then
336                 echo "skip: $tree.$compiler nothing changed in svn"
337                 touch "$log" "$err"
338                 send_logs "$log" "$err"
339                 unlock_file "$lck"
340                 return
341             fi
342         fi
343
344         # pull the tree
345         if ! fetch_tree "$tree"; then
346             unlock_file "$lck"
347             return
348         fi
349
350         if [ ! -x $srcdir/configure ]; then
351                 echo "skip: $tree.$compiler configure not present, try again next time!"
352                 unlock_file "$lck"
353                 return
354         fi
355
356         if [ ! $USER = "" ]; then
357             whoami=$USER
358         else 
359             if [ ! $LOGNAME = "" ]; then
360                 whoami=$LOGNAME
361             else
362                 whoami=build
363             fi
364         fi
365
366         prefix="$test_root/prefix"
367         if [ ! -d $prefix ]; then
368                 mkdir $prefix
369         fi
370         prefix="$prefix/$tree"
371
372         smbtorture4=$test_root/smbtorture4
373         export smbtorture4
374
375         case "$tree" in
376         samba4)
377             config="$config --enable-socket-wrapper"
378             ;;
379         samba|samba_3_0)
380             config="$config --enable-socket-wrapper"
381             if [ -f $smbtorture4 ]; then
382                 # we create a local copy to make sure the same binary is used for all tests
383                 cp $smbtorture4 $smbtorture4.$tree 
384                 config="$config --with-smbtorture4-path=$smbtorture4.$tree"
385             fi
386             ;;
387         ldb)
388             # try to avoid having extra copies of popt lying around, or
389             # depending on libpopt-dev on every system
390             config="$config --with-popt-src=../../popt"
391             fetch_tree popt
392             ;;
393         talloc)
394             fetch_tree libreplace
395             ;;
396         *)
397             testsuite=testsuite
398             ;;
399         esac
400
401         config_and_prefix="$config --prefix=$prefix"
402
403         # see if we need to rebuild
404         sum_tree $test_root $tree $sum
405         echo "CFLAGS=$CFLAGS $config_and_prefix" >> $sum
406
407         if cmp "$sum" "$sum.old" > /dev/null; then
408                 echo "skip: $tree.$compiler nothing changed"
409                 touch "$log" "$err"
410                 send_logs "$log" "$err"
411                 unlock_file "$lck"
412                 return
413         fi
414
415         # we do need to rebuild - save the old sum
416         /bin/rm -f $sum.old
417         mv $sum $sum.old
418
419         actions="$*"
420         
421         if [ "$actions" = "" ]; then
422             actions="configure build install test"
423         fi
424
425         # start the build
426         (
427                 uname -a
428
429                 # we need to be able to see if a build farm machine is accumulating
430                 # stuck processes. We do this in two ways, as we don't know what style
431                 # of ps it will have
432                 ps xfuw 2> /dev/null
433                 ps -fu $USER 2> /dev/null
434
435                 echo "building $tree with CC=$compiler on $host at "`date`
436
437                 # build the timelimit utility
438                 echo "Building timelimit"
439                 mkdir -p $builddir
440                 $compiler $TIMELIMIT_FLAGS -o $builddir/timelimit $test_root/timelimit.c || exit 1
441
442                 if [ -r $test_root/$tree.svn ]; then
443                   h_rev=`grep revision= $test_root/$tree.svn | head -1 | cut -d'"' -f2`
444                   if [ -n "$h_rev" ]; then
445                         echo "HIGHEST SVN REVISION: $h_rev"
446                   fi
447                   rev=`grep committed-rev= $test_root/$tree.svn | head -1 | cut -d'"' -f2`
448                   if [ -n "$rev" ]; then
449                         echo "BUILD REVISION: $rev"
450                   fi
451                 fi
452
453                 for action in $actions; do
454
455                     echo Running action $action
456
457                     date
458
459                     cd $builddir || exit 1
460                     export srcdir
461                     df .
462                     mount
463                     vmstat
464
465                     ( action_$action )
466                     action_status=$?
467                     
468                     if [ $action_status != 0 ]; then
469                         echo "ACTION FAILED: $action";
470                     else
471                         echo "ACTION PASSED: $action";
472                     fi
473                     
474                     if [ $action_status != 0 ]; then 
475                         break;
476                     fi
477
478                 done
479
480                 if [ "$noclean" = "yes" ]; then
481                     echo cleanup skipped!
482                 else
483                     echo cleaning up
484                     do_make clean
485                     /bin/rm -rf $prefix
486                 fi
487                 date
488         ) > "$log" 2> "$err"
489         
490         # send the logs to the master site
491         send_logs "$log" "$err"
492
493         # cleanup
494         unlock_file "$lck"
495 }
496
497
498 #########################################################
499 # enable this on a per host basis only when needed please
500 # (at least for the moment)
501 kill_old_processes() {
502     # this should work on systems with linux like ps
503     (ps uxfw | grep /build | grep -v grep | egrep 'AM|PM|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec' | awk '{print $2}' | xargs kill -9) 2> /dev/null
504     # and this should work on sysv style ps
505     (ps -fu $USER | grep /build | grep -v grep | egrep 'AM|PM|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec' | awk '{print $2}' | xargs kill -9) 2> /dev/null
506 }
507
508
509 # this is a special fn that allows us to add a "special" hook to the build
510 # farm that we want to do to the build farm. never leave it empty. instead,
511 # use ":" as the fn body.
512 per_run_hook() {
513     # kill old processes on systems with a known problem
514     case $host in
515         nohost)
516             echo "just a placeholder";
517             ;;
518     esac
519 }
520
521
522 ######################################################
523 # main code that is run on each call to the build code
524 rsync --timeout=200 -q -az samba.org::build_farm/*.c .
525
526
527 # build.log can grow to an excessive size, trim it beyond 50M
528 if [ -f build.log ]; then
529   find build.log -size +100000 -exec /bin/rm '{}' \;
530 fi
531