Index: ChangeLog from Clement Vasseur clement.vasseur@lrde.epita.fr
* auto-build/auto-build: Add support for building on several hosts. * auto-build/packages.list: Add more hosts.
Index: auto-build/auto-build --- auto-build/auto-build (revision 112) +++ auto-build/auto-build (working copy) @@ -32,16 +32,17 @@
=head1 NAME
-auto-build +auto-build - Auto Build System
=head1 SYNOPSIS
-auto-build [options] packages.list [style.css] +auto-build [options] packages.list
-m, --man display the manual -h, --help print this help and exit -V, --version print version information and exit -d, --delay=DELAY redo a build cycle after DELAY minutes + -c, --css=FILE use FILE for the style sheet
=head1 DESCRIPTION
@@ -50,81 +51,101 @@ use strict; use Getopt::Long; use Pod::Usage; +use File::Copy;
my $report_dir; -my $build_dir; -my $inst_dir; +my @hosts; my @packages; - -my %variables; my @colors; -my %deps; +my @info; +my %variables;
-my $packages; -my $css; -my $man = 0; -my $help = 0; +my $man; +my $help; my $delay = 0; +my $css;
GetOptions( 'man|m' => $man, 'help|h|?' => $help, 'version|V' => &version, 'delay|d=i' => $delay, + 'css|c=s' => $css ) or pod2usage(-verbose => 0);
pod2usage(-verbose => 1) if $help; pod2usage(-exitstatus => 0, -verbose => 2) if $man; +pod2usage(-verbose => 0) unless @ARGV;
-($packages, $css) = @ARGV; -pod2usage(-verbose => 0) unless defined $packages; - -&read_pkg_list($packages); -&create_dir($report_dir); -&create_dir($build_dir); -&create_dir($inst_dir); - -if (defined $css) { - system("/bin/cp "$css" "$report_dir/style.css"") - and die "$0: unable to cp `$css' to `$report_dir/style.css'"; -} else { - &print_css; -} - +&read_pkg_list($ARGV[0]); +&prepare_hosts; &prepare_pkgs; +&gen_css; +&gen_info; +&gen_report; +&gen_pkg_report($_) foreach @packages;
while (1) { - &auto_build; - last if $delay == 0; - sleep $delay * 60; + foreach my $host (@hosts) { + my $pid = fork; + defined $pid or die "$0: unable to fork: $!\n"; + unless ($pid) { + $_->{'do_build'} = 1 foreach @packages; + foreach my $pkg (@packages) { + $pkg->{'host'} = $host; + if (defined $pkg->{'hosts'}) { + my $na = 1; + foreach (split /\s+/, $pkg->{'hosts'}) { + if ($_ eq $host->{'name'}) { + $na = 0; + last; + } + } + if ($na) { + &set_status($pkg, 'na'); + next; + } + } + $pkg->{'env'} .= " $host->{'env'}" if defined $host->{'env'}; + delete $pkg->{'env'} unless $pkg->{'env'}; + &set_status($pkg, 'skipped') unless $pkg->{'do_build'}; + next if $pkg->{'do_build'} and &build_pkg($pkg, $host) eq 'succeeded'; + undef $_->{'do_build'} foreach @{$pkg->{'used_by'}}; + } + exit 0; + } + $host->{'pid'} = $pid; }
-sub auto_build { - &gen_summary; - + for (my $i = 0; $i < @hosts; ) { + sleep 1; + foreach my $host (@hosts) { foreach my $pkg (@packages) { - print "$pkg->{'name'}:\n"; - - &ch_dir($build_dir); - next if &check_revision($pkg); + my $file = "$report_dir/$pkg->{'name'}/$host->{'name'}/status"; + my $st = `cat "$file" 2>/dev/null`; + chomp($st); + $pkg->{'status'}->{$host->{'name'}} = '' unless + defined $pkg->{'status'}->{$host->{'name'}}; + if ($st ne $pkg->{'status'}->{$host->{'name'}}) { + if ($pkg->{'name'} eq $packages[-1]->{'name'} + and ($st eq 'succeeded' or $st eq 'failed' or $st eq 'na')) { + waitpid($host->{'pid'}, 0); + $i++; + } + $pkg->{'status'}->{$host->{'name'}} = $st; &gen_pkg_report($pkg); - - my $ok = 1; - foreach my $dep (@{$deps{$pkg->{'name'}}}) { - foreach (@packages) { - $ok = 0 if $_->{'name'} eq $dep - and ($_->{'status'} eq 'failed' or $_->{'status'} eq 'skipped'); + &gen_report; } - unless ($ok) { - &set_status($pkg, 'skipped'); - last; } } - - &build_pkg($pkg) if $ok; } + + last if $delay == 0; + sleep $delay * 60; }
+&gen_report; + sub xopen { my $filename = shift; my $name = $filename; @@ -141,40 +162,6 @@ close $FILE or die "$0: unable to close `$FILE': $!\n"; }
-sub header { - my ($filename, $title, $css) = @_; - my $FILE = &xopen(">$filename"); - select $FILE; - - $css = ("../" x $css) . 'style.css'; - - print <<HTML; -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" -"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> -<html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> - <title>$title</title> - <link rel="stylesheet" type="text/css" href="$css"/> - </head> - <body> -HTML - - return $FILE; -} - -sub footer { - print <<HTML; - <h4>Generated by <em>auto-build</em> version $VERSION</h4> - </body> -</html> -HTML - - select STDOUT; - my $FILE = shift; - &xclose($FILE); -} - sub read_pkg_list { my $filename = shift; my $LIST = &xopen($filename); @@ -198,19 +185,15 @@ next; }
- unless (defined $build_dir) { - $build_dir = $_; - next; - } - - unless (defined $inst_dir) { - $inst_dir = $_; - next; - } - if (m/^\s*color\s+(\w+)\s+"(.*?)"\s*$/) { push @colors, [ $2, $1 ];
+ } elsif (m/^\s*info\s+(.*?)\s*$/) { + push @info, split(/\s+/, $1); + + } elsif (m/^\s*host\s+"(.*)"\s*$/) { + push @hosts, { 'name' => $1 }; + } elsif (m/^\s*section\s+"(.*)"\s*$/) { $section = $1;
@@ -221,276 +204,306 @@ push @packages, { 'name' => $1, 'section' => $section, + 'wd' => '/', 'opt' => '', - 'cfg' => '', - 'rev' => '0' + 'env' => '', + 'cfg' => '' };
- } elsif (m/^\s*(\w\w\w)\s*:\s*(.*?)\s*$/) { + } elsif (m/^\s*(\w+)\s*:\s*(.*?)\s*$/) { my $field = $1; my $value = $2;
- my $err = 1; - foreach ('url', 'cfg', 'opt', 'env', 'dif', 'cpu') { - if ($field eq $_) { - $err = 0; - last; - } - } - - die "$filename:$.: invalid field `$field'\n" if $err; + if (defined $section) { while ($value =~ m/${([\w-]+)}/) { if (defined $variables{$1}) { $value =~ s/${([\w-]+)}/$variables{$1}/; } else { - $value =~ s/${([\w-]+)}/$inst_dir/$1/; - push @{$deps{$packages[-1]->{'name'}}}, $1; + $value =~ s/${([\w-]+)}/$DIR/usr/$1/; + foreach (@packages) { + push @{$_->{'used_by'}}, $packages[-1] if $_->{'name'} eq $1; } } + } + + $field =~ m/^(url|cfg|opt|env|diff|hosts)$/ + or die "$filename:$.: invalid field `$field'\n"; $packages[-1]->{$field} = $value;
} else { + $field =~ m/^(addr|dir|user|proc|env|make)$/ + or die "$filename:$.: invalid field `$field'\n"; + $hosts[-1]->{$field} = $value; + } + + } else { die "$filename:$.: syntax error\n"; } }
&xclose($LIST); - (defined $report_dir and defined $build_dir and $inst_dir) - or die "$0: `report', `build' and `inst' directories must be defined\n"; + die "$0: the report directory must be defined\n" unless defined $report_dir; }
-sub create_dir { - my $dir = shift; - return if -d $dir; - system("/bin/mkdir -p "$dir"") - and die "$0: unable to mkdir `$dir'\n"; -} +sub set_status { + my ($pkg, $status, $step) = @_; + my $file = "$report_dir/$pkg->{'name'}/$pkg->{'host'}->{'name'}/status";
-sub delete_dir { - my $dir = shift; - return unless -d $dir; - system("/bin/chmod -fR u+w "$dir"; /bin/rm -rf "$dir"") - and die "$0: unable to remove `$dir'\n"; + if (defined $step) { + return unless defined $step->{'name'}; + $file =~ s/status$/$step->{'name'}.status/; + } else { + $pkg->{'status'} = $status; + print "$pkg->{'host'}->{'name'}:$pkg->{'name'}:$status\n"; }
-sub ch_dir { - my $dir = shift; - chdir $dir or die "$0: unable to chdir `$dir': $!\n"; + system("echo "$status" > "$file"") + and die "$0: unable to create `$file'\n"; }
-sub time_to_str { - $_ = shift; - my $t = ''; +sub header { + my ($filename, $title, $css) = @_; + my $FILE = &xopen(">$filename"); + select $FILE; + + $css = ("../" x $css) . 'style.css'; + + print <<HTML; +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> + <title>$title</title> + <link rel="stylesheet" type="text/css" href="$css"/> + </head> + <body> +HTML
- if (defined $_ and $_ ne '') { - $t = ($_ % 60) . "s"; - $t = (($_/60) % 60) . "m$t" if $_ >= 60; - $t = (($_/(60 * 60)) % 60) . "h$t" if $_ >= 60 * 60; + return $FILE; }
- return $t; +sub footer { + print <<HTML; + <h4>Generated by <em>auto-build</em> version $VERSION</h4> + </body> +</html> +HTML + + select STDOUT; + my $FILE = shift; + &xclose($FILE); }
-sub gen_summary { +sub gen_report { my $SUMMARY = &header("$report_dir/index.html", "Auto Build System", 0); my $section = '';
print <<HTML; <h1>Auto Build System</h1> <table> + <tr> + <td class="left"></td> +HTML + + foreach (@hosts) { + print <<HTML; + <td style="width:7em"> + <a href="info/$_->{'name'}.html">$_->{'name'}</a><br/> + <span class="mach">$_->{'type'}</span> + </td> HTML + } + + print " </tr>\n";
foreach my $pkg (@packages) { if ($pkg->{'section'} ne $section) { - $section = $pkg->{'section'}; print <<HTML; <tr> - <td colspan="3"> - <h3>$section</h3> - </td> + <td class="left"><h3>$pkg->{'section'}</h3></td> </tr> HTML + $section = $pkg->{'section'}; }
- $pkg->{'status'} = '' unless defined $pkg->{'status'}; - - my $time = &time_to_str($pkg->{'time'}); - print <<HTML; <tr class="body"> - <td class="left" style="width:10em"> + <td class="left"> <a href="$pkg->{'name'}/index.html">$pkg->{'name'}</a> </td> - <td style="width:7em" class="st_$pkg->{'status'}">$pkg->{'status'}</td> - <td style="width:7em" class="time">$time</td> - </tr> HTML + foreach my $host (@hosts) { + my $status = $pkg->{'status'}->{$host->{'name'}}; + $status = '' unless defined $status; + my $sn = $status; + $sn = 'n/a' if $sn eq 'na'; + print " <td class="st_$status">$sn</td>\n"; + } + print " </tr>\n"; }
- print <<HTML; - </table> -HTML + print " </table>\n"; &footer($SUMMARY); }
sub gen_pkg_report { my $pkg = shift; my $filename = "$report_dir/$pkg->{'name'}/index.html"; - my $REPORT = &header("$filename", "$pkg->{'name'} report", 1); + my $REPORT = &header("$filename", "$pkg->{'name'} build report", 1);
- my ($ts, $tf) = ('', ''); - $ts = localtime $pkg->{'time_started'} if defined $pkg->{'time_started'}; - $tf = localtime $pkg->{'time_finished'} if defined $pkg->{'time_finished'}; - - print " <h1>$pkg->{'name'}</h1>\n"; - - if (defined $pkg->{'archives'}) { - foreach (@{$pkg->{'archives'}}) { - print " <a href="$_">$_</a><br/>\n" if -f $_; - } + print <<HTML; + <h1>$pkg->{'name'}</h1> + <table> + <tr> + <td style="width:6em"></td> +HTML + foreach (@hosts) { + print <<HTML; + <td style="width:7em"> + $_->{'name'}<br/> + <span class="mach">$_->{'type'}</span> + </td> +HTML } - - print " <h5>Build started: $ts</h5>\n" if $ts; - print " <table cellpadding="8">\n"; + print " </tr>\n";
foreach my $step (@{$pkg->{'steps'}}) { next unless defined $step->{'name'}; - if (defined $step->{'status'}) { - my $time = &time_to_str($step->{'time'}); - print <<HTML; <tr class="body"> - <td class="left" style="width:8em"> - <a href="$step->{'name'}.html">$step->{'name'}</a> - </td> - <td style="width:7em" class="st_$step->{'status'}">$step->{'status'}</td> - <td style="width:7em" class="time">$time</td> - </tr> + <td class="left">$step->{'name'}</td> HTML - } else { + foreach (@hosts) { + my $file = "$report_dir/$pkg->{'name'}/$_->{'name'}/$step->{'name'}"; + chomp(my $status = `cat "$file.status" 2>/dev/null`); + if ($status) { print <<HTML; - <tr class="body"> - <td class="left" style="width:8em">$step->{'name'}</td> - <td style="width:6em" /> - <td style="width:6em" /> - </tr> + <td> + <a href="$_->{'name'}/$step->{'name'}.html"> + <span class="st_$status">$status</span> + </a> + </td> HTML + } else { + print " <td></td>\n"; + } } + print " </tr>\n"; }
print " </table>\n"; - print " <h5>Build finished: $tf</h5>\n" if $tf; &footer($REPORT); }
-sub set_status { - $_[0]->{'status'} = $_[1]; - system("echo "$_[1]" > "$build_dir/$_[0]->{'name'}/.status"") - and die "$0: unable to create `$build_dir/$_[0]->{'name'}/.status'\n"; - print " - $_[1]\n"; - &gen_summary; -} - sub gen_log_page { - my ($pkg, $step) = @_; - my $filename = "$report_dir/$pkg->{'name'}/$step->{'name'}.html"; - my $REPORT = &header("$filename", "$pkg->{'name'} - $step->{'name'}", 1); - - print <<HTML; - <h1>$pkg->{'name'} - $step->{'name'}</h1> - <h5>$step->{'cmd'}</h5> - <a href="$step->{'name'}.log">View log</a> -HTML - - &footer($REPORT); -} - -sub run { - my ($pkg, $step) = @_; - my $status = $step->{'name'}; - my $out = "$report_dir/$pkg->{'name'}/$status"; - - &set_status($pkg, $status); - &gen_log_page($pkg, $step); - - my $t = time; - my $exit_code = system("$step->{'cmd'} >$out.log 2>&1"); - $step->{'time'} = time - $t; - - my $REPORT = &header("$out.html", "$pkg->{'name'} - $status", 1); + my ($pkg, $step, $log) = @_; + my $host = "$pkg->{'host'}->{'name'}"; + my $filename = "$report_dir/$pkg->{'name'}/$host/$step->{'name'}.html"; + my $title = "$pkg->{'name'} - $host - $step->{'name'}"; + my $REPORT = &header($filename, $title, 2);
print <<HTML; - <h1>$pkg->{'name'} - $step->{'name'}</h1> + <h1>$title</h1> <h5>$step->{'cmd'}</h5> - <pre> HTML
- my $LOG = &xopen("$out.log"); - my $archives_ready; + if (defined $log) { + my $LOG = &xopen($log);
+ print " <pre>\n"; while (<$LOG>) { - s/</</g; - s/>/>/g; + s/</</g; foreach my $c (@colors) { - if (m/$c->[0]/) { + next unless m/$c->[0]/; s/^(.*?)($c->[0])(.*)$/$1<span style="color:$c->[1]">$2</span>$3/g; last; } - } - if ($status eq 'distcheck') { - if (($archives_ready and m/^($archives_ready.tar.(gz|bz2))$/) - or m/^(.*.tar.(gz|bz2)) is ready for distribution$/) { - push @{$pkg->{'archives'}}, $1; - system("/bin/cp "$1" "$report_dir/$pkg->{'name'}"") - and die "$0: unable to cp `$1' to `$report_dir/$pkg->{'name'}': $!\n"; - } - $archives_ready = $1 if m/^(.*) archives ready for distribution: $/; - } print; } - print "</pre>\n"; &xclose($LOG); + + } else { + print " <a href="$step->{'name'}.log">View log</a>\n"; + } + &footer($REPORT); - return undef if $exit_code; - return 1; }
-sub check_revision { - my $pkg = shift; - my $revfile = "$build_dir/$pkg->{'name'}/.rev"; - my $rev; +sub gen_info { + my @uname = ( + [ 'Operating system', 'sr' ], [ 'Processor', 'm' ] + );
- if ($pkg->{'url'} =~ m|^svn:(.*/([^/]+))$|) { - chomp($rev = `svn log -q "https:$1" 2>/dev/null | grep '^r' | head -n 1`); - $rev =~ s/^r(\d+).*$/$1/; - } elsif ($pkg->{'url'} =~ m/^((ht|f)tp:.*/([^/]+))$/) { - chomp($rev = `wget -q -N -P "$build_dir/$pkg->{'name'}" "$1" && - md5sum "$build_dir/$pkg->{'name'}/$3"`); - } - $pkg->{'rev'} = $rev; - $pkg->{'rev'} = '0' unless defined $pkg->{'rev'}; - - if (-f $revfile) { - chomp($rev = `cat "$revfile"`); - unlink $revfile if $pkg->{'rev'} ne $rev; - } - if (-f $revfile) { - chomp($pkg->{'time'} = `cat "$build_dir/$pkg->{'name'}/.time"`); - chomp($pkg->{'status'} = `cat "$build_dir/$pkg->{'name'}/.status"`); - &set_status($pkg, $pkg->{'status'}); - return 1; + foreach my $host (@hosts) { + print "generating info for $host->{'name'}\n"; + + my $INFO = &header("$report_dir/info/$host->{'name'}.html", + "$host->{'name'} info", 1); + print <<HTML; + <h1>$host->{'name'} info</h1> + <div class="left"> + <b>Host:</b> $host->{'addr'}<br/> +HTML + foreach my $i (@uname) { + &execute($host, "uname -$i->[1]", ".$$.out"); + print " <b>$i->[0]:</b> ", `cat .$$.out`, "<br/>\n"; + } + print " <b>Environment:</b> $host->{'env'}<br/>\n" + if defined $host->{'env'}; + print " </div>\n"; + + foreach my $prog (sort @info) { + if (&execute($host, "$prog --version", ".$$.out") == 0 + or &execute($host, "$prog -V", ".$$.out") == 0) { + print " <h4>$prog</h4>\n<pre>", `sed 's/</\</g' < .$$.out`, + "</pre>\n"; + } + } + unlink ".$$.out"; + &footer($INFO); } - return undef; }
-sub get_package { - my $pkg = shift; +sub prepare_hosts { + foreach my $host (@hosts) { + my $cmd = "uname -mo 2>/dev/null || uname -ps | + sed "s/\(.*\) \(.*\)/\2 \1/""; + &execute($host, $cmd, ".$$.out"); + chomp($host->{'type'} = `cat .$$.out; rm -f .$$.out`); + $host->{'make'} = 'make' unless defined $host->{'make'}; + $host->{'make'} .= ' -k'; + $host->{'make'} .= " -j $host->{'proc'}" if defined $host->{'proc'}; + } +} + +sub prepare_pkgs { + my $bootstrap = 'if [ -x bootstrap ]; then ./bootstrap; else if ' . + '[ -x ./bootstrap.sh ]; then ./bootstrap.sh; else autoreconf -fvi; fi; fi'; + + system("/bin/mkdir -p "$report_dir/info"") + and die "$0: unable to mkdir `$report_dir/info'\n"; + + foreach my $pkg (@packages) { my @steps; + + $_ = ""$DIR/src/$pkg->{'name'}""; + push @steps, { + 'cmd' => "( /bin/chmod -fR u+w $_; /bin/rm -rf $_; ) 2> /dev/null; " . + "/bin/mkdir -p $_", + 'dir' => "echo $_" + }; + + foreach (@hosts) { + my $dir = "$report_dir/$pkg->{'name'}/$_->{'name'}"; + system("/bin/mkdir -p "$dir"") + and die "$0: unable to mkdir `$dir'\n"; + } + $_ = $pkg->{'url'};
- if (m|^http://.*/(%5B%5E/%5D+)/?$%7C - or m|^ftp://.*/([^/]+)/?$|) { + if (m|^http://.*/(%5B%5E/%5D+)/?$%7C or m|^ftp://.*/([^/]+)/?$|) { $_ = "file://$1"; push @steps, { 'name' => 'download', @@ -498,17 +511,14 @@ }; }
- if (m|^file://(.*)$| and -d $1 and /^([^/]*)/(.*)$/) { - my $dir = $1; - $pkg->{'dir'} = $2; - + if (m|^file://(.*)$| and -d $1 and m/^([^/]*)/(.*)$/) { push @steps, { 'name' => 'copy', - 'cmd' => "cp -r "$dir" ." + 'cmd' => "scp -r "$1" .", + 'dir' => "echo "$2"" }, { - 'dir' => "echo "$pkg->{'dir'}"", 'name' => 'bootstrap', - 'cmd' => "./bootstrap" + 'cmd' => $bootstrap };
} elsif (m|^file://(.*)$|) { @@ -517,169 +527,183 @@
$c = "z" if m/.tar.gz$/; $c = "j" if m/.tar.bz2$/; - $pkg->{'dir'} = $file;
if (defined $c) { push @steps, { 'name' => 'unpack', - 'cmd' => "tar -x${c}vf "$file"" - }, { - 'dir' => "tar -t${c}f "$file" | head -n 1 | cut -d '/' -f 0-1", + 'cmd' => "tar -x${c}vf "$file"", + 'dir' => "echo "$DIR/src/$pkg->{'name'}/`tar -t${c}f "$file" | " . + "head -n 1 | cut -d '/' -f 1`"" }; }
} elsif (m|^svn://(.*/([^/]+))/?$|) { - my $repository = "https://$1"; - $pkg->{'dir'} = $2; - push @steps, { 'name' => 'checkout', - 'cmd' => "svn checkout "$repository"" + 'cmd' => "svn checkout "https://$1%5C"", + 'dir' => "echo "$DIR/src/$pkg->{'name'}/$2"" }, { - 'dir' => "echo "$pkg->{'dir'}"", 'name' => 'bootstrap', - 'cmd' => '(./bootstrap || ./bootstrap.sh || autoreconf -fvi)' + 'cmd' => $bootstrap };
} elsif (m|^prcs://(.*)$|) { - $pkg->{'dir'} = $1; - push @steps, { - 'dir' => "echo "$1"", + 'cmd' => "/bin/mkdir "$DIR/src/$pkg->{'name'}/$1"", + 'dir' => "echo "$DIR/src/$pkg->{'name'}/$1"" + }, { 'name' => 'checkout', - 'cmd' => "prcs checkout "$1"" + 'cmd' => "prcs checkout -f "$1"" }, { 'name' => 'bootstrap', - 'cmd' => '(./bootstrap || ./bootstrap.sh || autoreconf -fvi)' + 'cmd' => $bootstrap };
} else { die "$0: invalid URL `$_': unknown protocol\n"; }
- return @steps; -} - -sub prepare_pkgs { - foreach my $pkg (@packages) { - my @steps = &get_package($pkg); - my $dir = "$report_dir/$pkg->{'name'}"; - &create_dir("$build_dir/$pkg->{'name'}"); - &create_dir($dir); - - if (defined $pkg->{'dif'}) { + if (defined $pkg->{'diff'}) { my $bootstrap; $bootstrap = pop @steps if $steps[-1]->{'name'} eq 'bootstrap'; push @steps, { 'name' => 'patch', - 'cmd' => "patch -p0 -t -i "$pkg->{'dif'}"" + 'cmd' => "patch -p0 -t -i "$pkg->{'diff'}"" }; - if (defined $bootstrap) { - if (defined $bootstrap->{'dir'}) { - $steps[-1]->{'dir'} = $bootstrap->{'dir'}; - undef $bootstrap->{'dir'}; - } - push @steps, $bootstrap; - } + push @steps, $bootstrap if defined $bootstrap; }
- my $cpu = ''; - $cpu = " -j $pkg->{'cpu'}" if defined $pkg->{'cpu'}; + my $prefix = ""$DIR/usr/$pkg->{'name'}"";
push @steps, { 'name' => 'configure', - 'cmd' => "./configure --prefix=$inst_dir/$pkg->{'name'} $pkg->{'cfg'}" + 'cmd' => "./configure --prefix=$prefix $pkg->{'cfg'}" }, { - 'name' => 'build', 'cmd' => "make$cpu" + 'name' => 'build', + 'cmd' => '$MAKE' };
+ push @steps, { + 'name' => 'check', + 'cmd' => '$MAKE check' + } unless $pkg->{'opt'} =~ m/\bno-check\b/; + my $dcf = ''; defined $pkg->{'cfg'} and $pkg->{'cfg'} ne '' and $dcf = "DISTCHECK_CONFIGURE_FLAGS="$pkg->{'cfg'}" ";
push @steps, { - 'name' => 'check', - 'cmd' => "make$cpu -k check" - }, { 'name' => 'distcheck', - 'cmd' => "make$cpu -k ${dcf}distcheck" + 'cmd' => "$MAKE ${dcf}distcheck" } unless $pkg->{'opt'} =~ m/\bno-check\b/;
push @steps, { - 'rm' => "$inst_dir/$pkg->{'name'}", + 'cmd' => "( /bin/chmod -fR u+w $prefix; /bin/rm -rf $prefix; ) " . + "2>/dev/null; :" + }, { 'name' => 'install', - 'cmd' => 'make install' + 'cmd' => '$MAKE install' + }; + + $_ = ""$DIR/src/$pkg->{'name'}""; + push @steps, { + 'cmd' => "/bin/chmod -fR u+w $_; cd / && /bin/rm -rf $_" };
$pkg->{'steps'} = @steps; - next if &check_revision($pkg); - &gen_pkg_report($pkg) unless -f "$dir/index.html"; } }
sub build_pkg { - my $pkg = shift; - my %env = %ENV; + my ($pkg, $host) = @_; + my $st;
- if (defined $pkg->{'env'}) { - foreach (split /\s*,\s*/, $pkg->{'env'}) { - if (m/^\s*(\w+)\s*=\s*"(.*)"\s*$/) { - my ($v, $w) = ($1, $2); - $w =~ s/$(\w+)/$ENV{$1}/; - $ENV{$v} = $w; + foreach my $step (@{$pkg->{'steps'}}) { + &set_status($pkg, "running", $step); + unless (&run($pkg, $step)) { + &set_status($pkg, $st = "failed", $step); + last; + } + if (defined $step->{'dir'}) { + my $cmd = "cd "$pkg->{'wd'}" && ( $step->{'dir'}; )"; + $cmd =~ s/$DIR/$pkg->{'host'}->{'dir'}/g; + &execute($pkg->{'host'}, $cmd, ".$$.out"); + chomp($pkg->{'wd'} = `cat .$$.out; rm -f .$$.out`); } + &set_status($pkg, $st = "succeeded", $step); } + &set_status($pkg, $st); + return $st; }
- my $st; - my $dir = "$build_dir/$pkg->{'name'}"; - &delete_dir($dir); - &create_dir($dir); - &ch_dir($dir); - $pkg->{'time_started'} = time; +sub run { + my ($pkg, $step) = @_;
- foreach my $step (@{$pkg->{'steps'}}) { - $step->{'status'} = "running"; - &gen_pkg_report($pkg); - &delete_dir($step->{'rm'}) if defined $step->{'rm'}; - if (defined $step->{'dir'}) { - chomp($pkg->{'dir'} = `$step->{'dir'}`); - &create_dir($pkg->{'dir'}); - &ch_dir($pkg->{'dir'}); - } - if (not defined $step->{'cmd'} - or &run($pkg, $step)) { - $step->{'status'} = $st = "succeeded"; - next; + my $env = ''; + if (defined $pkg->{'env'}) { + $pkg->{'env'} =~ s/^\s*(.*?)\s*$/$1/; + foreach (split /\s+/, $pkg->{'env'}) { + $env .= "$1 " if m/^(\w+)=/; } - $step->{'status'} = $st = "failed"; - last; + $env = "$pkg->{'env'} && export $env && "; }
- $pkg->{'time_finished'} = time; - $pkg->{'time'} = $pkg->{'time_finished'} - $pkg->{'time_started'}; - %ENV = %env; - &gen_pkg_report($pkg); - &ch_dir($build_dir); - &set_status($pkg, $st); - foreach ('rev', 'time', 'status') { - system("echo "$pkg->{$_}" > "$build_dir/$pkg->{'name'}/.$_""); + my $cmd = "${env}cd "$pkg->{'wd'}" && ( $step->{'cmd'}; )"; + + foreach ('dir', 'make') { + $cmd =~ s/$\U$_/$pkg->{'host'}->{$_}/g; + $step->{'cmd'} =~ s/$\U$_/$pkg->{'host'}->{$_}/g; + } + + unless (defined $step->{'name'}) { + &execute($pkg->{'host'}, $cmd, ".$$.out") + and die "$0: unable to execute `$cmd' on $pkg->{'host'}->{'name'}\n"; + unlink ".$$.out"; + return 1; + } + + my $status = $step->{'name'}; + my $out = "$report_dir/$pkg->{'name'}/$pkg->{'host'}->{'name'}/$status"; + &set_status($pkg, $status) unless $status eq 'unnamed'; + &gen_log_page($pkg, $step); + my $r = &execute($pkg->{'host'}, $cmd, "$out.log"); + &gen_log_page($pkg, $step, "$out.log"); + return undef if $r; + return 1; } - &delete_dir("$pkg->{'name'}/$pkg->{'dir'}") if ($st eq "succeeded") - and ($pkg->{'opt'} =~ m/\brm-build-dir\b/); + +sub execute { + my ($host, $cmd, $out) = @_; + + unlink $out; + my $h = $host->{'addr'}; + $h = "$host->{'user'}@$h" if defined $host->{'user'}; + my $c = &xopen(">.$$"); + print $c "rm -f $0\n$cmd\n"; + &xclose($c); + return system("scp -q .$$ $h:.$host->{'name'}.cmd && rm -f .$$ && + ssh $h sh .$host->{'name'}.cmd > $out 2>&1"); }
sub version { - print "auto-build (Auto Build System) $VERSION\n", - "Written by Clement Vasseur and Nicolas Pouillard.\n\n", - "Copyright (C) 2004 LRDE - EPITA Research and Development Laboratory.\n", - "This is free software; see the source for copying conditions. ", - "There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A ", - "PARTICULAR PURPOSE.\n"; + print <<EOF; +auto-build (Auto Build System) $VERSION +Written by Clement Vasseur and Nicolas Pouillard. + +Copyright (C) 2004 LRDE - EPITA Research and Development Laboratory. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +EOF exit 0; }
-sub print_css { +sub gen_css { + if (defined $css) { + ©($css, "$report_dir/style.css") + or die "$0: unable to copy `$css' to `$report_dir/style.css': $!\n"; + return; + } + my $CSS = &xopen(">$report_dir/style.css"); print $CSS <<CSS; body { @@ -687,13 +711,12 @@ background-color: #EEEEEE; font-family: Verdana, Helvetica, sans-serif; } - h1,h2,h3,h4,h5,h6 { font-family: Verdana, Helvetica, sans-serif; color: #003377; } - .left { text-align: left; } +.mach { font-size: xx-small; color: #003377; font-weight: bold; } table { margin-left:auto; margin-right:auto; } h1,h4 { text-align: center; background-color: #CCCCFF; } h3 { text-align: left; text-indent: 1em } @@ -702,11 +725,11 @@ pre { text-align: left; font-family: Courier, monospace; } tr { text-indent: 0em; text-align: center; } td { text-indent: 0em; font-family: Verdana, Helvetica, sans-serif; } -tr.body { background-color: #E5E5E5; } -td.time { color: gray } -td.st_succeeded { color: green } -td.st_failed { color: red } -td.st_skipped { color: gray } +tr.body { background-color: #E5E5E5 } +.st_succeeded { color: green } +.st_failed { color: red } +.st_skipped { color: gray } +.st_na { color: gray } CSS &xclose($CSS); } Index: auto-build/packages.list --- auto-build/packages.list (revision 112) +++ auto-build/packages.list (working copy) @@ -1,27 +1,72 @@ ### Auto Build System #########################################################
# report directory -/mnt/ghost/stud/vasseu_c/www/build - -# build directory -/work/auto-build/src - -# inst directory -/work/auto-build/usr +/mnt/ghost/lrde-2005/vasseu_c/www/build/current
### Color highlighting ########################################################
-color red "^make.*: *** .*$" +color red "^g?make.*: *** .*$" color red "^SdfChecker:error:.*$" +color red "^ERROR:.*$" color maroon "^warning:.*$" color maroon "^SdfChecker:warning:.*$" -color maroon "^[\w/.]+:\d+: [Ww]arning:.*$" -color red "^[\w/.]+: In .*$" -color gray "^make.*:.*$" +color maroon "^[\w/.-]+:\d+: [Ww]arning:.*$" +color red "^[\w/.-]+:\d+: error:.*$" +color red "^/bin/bash:.*$" +color gray "^g?make.*:.*$" color green "^PASS:" color blue "^XPASS:" color red "^FAIL:"
+### Hosts ##################################################################### + +host "caracas" + + addr: caracas.lrde.epita.fr + dir: /work/auto-build + +#------------------------------------------------------------------------------ + +host "ustaritz" + + addr: ustaritz.lrde.epita.fr + dir: /tmp/auto-build + make: gmake + env: CXX=g++34 + +#------------------------------------------------------------------------------ + +host "woods-hole" + + addr: woods-hole.lrde.epita.fr + dir: /tmp/auto-build + env: CPPFLAGS="-I$HOME/darwin/include" LDFLAGS="-L$HOME/darwin/lib" + +#------------------------------------------------------------------------------ + +host "jussieu" + + addr: jussieu.epita.fr + user: vasseu_c + dir: /goinfre/lrde-auto-build + make: gmake + env: CPPFLAGS="-I$HOME/usr/include" LDFLAGS="-L$HOME/usr/lib" + +#------------------------------------------------------------------------------ + +host "maya" + + addr: maya.epita.fr + user: vasseu_c + dir: /goinfre/lrde-auto-build + make: gmake + env: CPPFLAGS="-I$HOME/sun/include" LDFLAGS="-L$HOME/sun/lib" + +### Information about software versions ####################################### + +info make gcc g++ bison python automake autoconf libtool \ + doxygen gmake g++34 tar awk icpc + ### Tiger #####################################################################
section "Tiger" @@ -31,7 +76,6 @@ havm
url: svn://svn.lrde.epita.fr/svn/havm/trunk - dif: /home/lrde/lrde-2005/vasseu_c/havm.diff
#------------------------------------------------------------------------------
@@ -39,11 +83,40 @@
url: svn://svn.lrde.epita.fr/svn/nolimips/trunk
+#------------------------------------------------------------------------------ + +tc + + url: svn://svn.lrde.epita.fr/svn-lrde/tc/trunk + hosts: caracas ustaritz woods-hole + ### StrategoXT ################################################################
-aterm = /home/lrde/lrde/usr/Aterm -sdf = /home/lrde/lrde/usr/Sdf -strategoxt = /home/lrde/lrde/usr/StrategoXT +section "StrategoXT" + +#------------------------------------------------------------------------------ + +aterm + + url: http://www.cwi.nl/projects/MetaEnv/aterm/aterm-2.2.tar.gz + cfg: --with-gcc + +#------------------------------------------------------------------------------ + +sdf + + url: ftp://ftp.stratego-language.org/pub/stratego/sdf2/sdf2-bundle-2.2.tar.gz + cfg: --with-aterm=${aterm} + opt: no-check + +#------------------------------------------------------------------------------ + +strategoxt + + url: ftp://ftp.stratego-language.org/pub/stratego/StrategoXT/strategoxt-0.12.tar.gz + cfg: --with-aterm=${aterm}\ + --with-sdf=${sdf} + opt: no-check
### Transformers ##############################################################
@@ -127,14 +200,14 @@ --with-sdf-astgen=${sdf-astgen}\ --with-sdf-attribute=${sdf-attribute}\ --with-esdf=${esdf} - env: PATH="/mnt/daily/usr/stratego-shell/bin:${strategoxt}/bin:$PATH" + env: PATH="${strategoxt}/bin:$PATH" + hosts: caracas ustaritz jussieu maya
#------------------------------------------------------------------------------
cxx-grammar
url: svn://svn.lrde.epita.fr/svn/transformers/trunk/cxx-grammar - dif: /home/lrde/lrde-2005/vasseu_c/cxx-grammar.diff cfg: --with-aterm=${aterm}\ --with-sdf=${sdf}\ --with-strategoxt=${strategoxt}\ @@ -180,9 +253,16 @@ olena
url: prcs://oln - cpu: 2 - env: PRCS_REPOSITORY="/home/lrde/admin/prcs/repository",\ - CXX="g++-3.4" + env: PRCS_REPOSITORY="/home/lrde/admin/prcs/repository" + hosts: caracas ustaritz woods-hole + +#------------------------------------------------------------------------------ + +olena-icc + + url: prcs://oln + env: PRCS_REPOSITORY="/home/lrde/admin/prcs/repository" CXX="icpc" + hosts: caracas
### Vaucanson #################################################################
@@ -193,8 +273,13 @@ vaucanson
url: svn://svn.lrde.epita.fr/svn/vaucanson/trunk - cpu: 2 - env: PATH="/home/lrde/lrde-2005/vasseu_c/usr/bin/old:$PATH",\ - CXX="g++-3.3" + +#------------------------------------------------------------------------------ + +vaucanson-icc + + url: svn://svn.lrde.epita.fr/svn/vaucanson/trunk + env: CXX="icpc" + hosts: caracas
#------------------------------------------------------------------------------