LT 127: Update auto-build to the latest version

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://.*/([^/]+)/?$| - or m|^ftp://.*/([^/]+)/?$|) { + if (m|^http://.*/([^/]+)/?$| 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\"", + '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 #------------------------------------------------------------------------------
participants (1)
-
Clement Vasseur