Index: ChangeLog
from Clement Vasseur <clement.vasseur(a)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…
+ 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
#------------------------------------------------------------------------------