blob: 4ecd654db09b30cff781fbefc03551c8aab0a5f5 [file] [log] [blame]
#!/usr/bin/perl
use strict;
use Data::Dumper;
use Getopt::Std;
use IO::File;
our %opts = (d => 'size-tests');
# default arguments go here
my @sets =
({
"with-defaults" => '',
});
my %base_args = %{$sets[0]};
my ($basename, $basenum);
getopts('t:hlcD:nj:o:eb:T', \%opts) || usage();
$opts{'j'} = "-j$opts{j}" if (exists($opts{'j'}));
usage() if ($opts{'h'});
my @argumentsets =
(
{
title => 'security-types',
arguments =>
{
usm => {
'with-security-modules' => 'usm',
},
dtlsandtls => {
'with-security-modules' => 'tsm',
'with-out-security-modules' => 'usm',
'with-transports' => 'DTLSUDP TLSTCP',
'with-mib-modules' => 'tlstm-mib tsm-mib'
},
usmanddtlsandtls => {
'with-security-modules' => 'tsm usm',
'with-transports' => 'DTLSUDP TLSTCP',
'with-mib-modules' => 'tlstm-mib tsm-mib'
}
}
},
{
title => 'minimalist',
arguments =>
{
minimal => {
'enable-minimalist' => '',
},
'not-minimal' => {
}
}
},
{
title => 'mib-loading',
arguments =>
{
'without-mib-loading' => {
'disable-mib-loading' => '',
},
'with-mib-loading' => {
}
}
},
{
title => 'debugging',
arguments =>
{
'without-debugging' => {
'disable-debugging' => '',
},
'with-debugging' => {
}
}
},
{
title => 'logging',
arguments =>
{
'without-logging' => {
'with-out-features' => 'logging',
},
'with-logging' => {
}
}
},
{
title => 'agent-mibs',
arguments =>
{
'full-agent' => {
},
'mini-agent' => {
'enable-mini-agent' => '',
}
}
},
{
title => 'protocol-support',
arguments =>
{
'everything' => {
},
'read-only' => {
'enable-read-only' => '',
},
'notify-only' => {
'enable-notify-only' => '',
}
}
},
{
title => 'perl',
arguments =>
{
'without-perl-modules' => {
'without-perl-modules' => '',
'disable-embedded-perl' => '',
},
'with-perl-no-embedding' => {
'with-perl-modules' => '',
'disable-embedded-perl' => '',
},
'with-perl-and-embedding' => {
'with-perl-modules' => '',
'enable-embedded-perl' => '',
}
}
},
);
# map these to a referencable lookup hash
my %argumentsets;
foreach my $set (@argumentsets) {
$argumentsets{$set->{'title'}} = $set;
}
if ($opts{'l'}) {
print "Types available:\n";
printf(" %-40.40s %s\n", "Test Title", "Number of subtests");
printf(" %-40.40s %s\n", "-" x 39, "-" x length("Number of subtests"));
foreach my $type (@argumentsets) {
my @keys = keys(%{$type->{'arguments'}});
printf(" %-40.40s %s\n", $type->{'title'}, $#keys+1);
}
exit;
}
my %types;
if ($opts{'t'}) {
my @types = split(/,\s*/, $opts{'t'});
foreach my $type (@types) {
$types{$type} = 1;
}
}
if ($opts{'b'}) {
# use this set as the base default set of arguments
($basename, $basenum) = ($opts{'b'} =~ /(.*):(\d+)/);
if (!exists($argumentsets{$basename})) {
printf STDERR "failed to find set for -b argument: %s\n", $basename;
exit(1);
}
@sets = add_in_flags($argumentsets{$basename}, \%base_args, ());
@sets = @sets[$basenum];
%base_args = %{$sets[0]};
}
foreach my $set (@argumentsets) {
if (!$opts{'t'} || exists($types{$set->{'title'}})) {
if ($basename && $set->{'title'} eq $basename) {
next;
}
@sets = add_in_flags($set, \%base_args, @sets);
}
}
if ($opts{'c'}) {
# print the configure flags
foreach my $set (@sets) {
print "$set->{'title'}:\n";
print " ", generate_configure_flags($set), "\n";
}
exit;
}
my $summaryfile;
if ($opts{'o'} && !$opts{'n'}) {
$summaryfile = new IO::File;
$summaryfile->open(">$opts{o}");
}
my $count = 0;
foreach my $set (@sets) {
$count++;
build_set($count, $set);
}
sub add_in_flags {
my ($argumentset, $base_flags, @current_flags) = @_;
my @new_flags;
# do a linear search of the options
if (! $opts{'e'}) {
@new_flags = @current_flags;
foreach my $newargs (keys(%{$argumentset->{'arguments'}})) {
my %flags = %$base_flags;
$flags{'title'} = "$flags{'title'}:$newargs";
foreach my $newflag (keys(%{$argumentset->{'arguments'}{$newargs}})) {
$flags{$newflag} .= " $argumentset->{'arguments'}{$newargs}{$newflag}";
}
push @new_flags, \%flags;
}
return @new_flags;
}
# or an exponential search
foreach my $flags (@current_flags) {
foreach my $newargs (keys(%{$argumentset->{'arguments'}})) {
my %flags = %{$flags}; # copy the existing hash-set of flags
if (exists($flags{'title'})) {
$flags{'title'} .= ", $newargs";
} else {
$flags{'title'} .= "$newargs";
}
foreach my $newflag (keys(%{$argumentset->{'arguments'}{$newargs}})) {
$flags{$newflag} .= " $argumentset->{'arguments'}{$newargs}{$newflag}";
}
push @new_flags, \%flags;
}
}
return @new_flags;
}
sub generate_configure_flags {
my ($arguments) = @_;
my $line = "";
foreach my $arg (keys(%$arguments)) {
next if ($arg eq 'title');
if ($arguments->{$arg} =~ /^\s*$/) {
$line .= " --$arg";
} else {
$line .= " --$arg=\"$arguments->{$arg}\"";
}
}
return $line;
}
sub build_set {
my ($num, $arguments) = @_;
$num = sprintf("%03d", $num);
my $file;
if (!$opts{'n'}) {
mkdir $opts{'d'} if (! -d $opts{'d'});
die "failed to create the $opts{'d'} directory" if (! -d $opts{'d'});
$file = new IO::File;
$file->open(">$opts{'d'}/$num-0-cmd-summary");
$file->print("Creating output for: $arguments->{'title'}\n");
}
print "==================== $arguments->{'title'}\n";
System ($file, $num, "1-distclean", "make distclean");
System ($file, $num, "2-configure",
"./configure " . generate_configure_flags($arguments));
System ($file, $num, "3-features", "make features");
System ($file, $num, "4-make", "make $opts{'j'}");
System ($file, $num, "5-unused-code", "perl local/minimalist/find-unused-code -g");
System ($file, $num, "6-testing", "make -C testing test") if ($opts{'T'});
if (!$opts{'n'}) {
analyze_size($arguments->{'title'}, "$opts{'d'}/$num-9-results");
}
}
sub analyze_size {
my ($title, $filename) = @_;
my $outfile = new IO::File;
$outfile->open(">$filename");
print "Results for: $title\n";
printf $outfile "Results for: $title\n";
printf ("%-50.50s %10s\n", "-" x 49, "-" x 10);
printf $outfile ("%-50.50s %10s\n", "-" x 49, "-" x 10);
my $totalsize = 0;
foreach my $buildfile (glob("snmplib/.libs/lib*.so.*.0.0"),
glob("agent/.libs/lib*.so.*.0.0"),
"agent/.libs/snmpd") {
my @info = stat($buildfile);
printf $outfile ("%-50.50s %10s\n", $buildfile, $info[7]);
printf("%-50.50s %10s\n", $buildfile, $info[7]);
$totalsize += $info[7];
}
printf $outfile ("%-50.50s %10s\n", "-" x 49, "-" x 10);
printf $outfile ("%-50.50s %10s bytes\n", "TOTAL", $totalsize);
printf("%-50.50s %10s\n", "-" x 49, "-" x 10);
printf("%-50.50s %10s bytes\n", "TOTAL", $totalsize);
if (defined($summaryfile)) {
my $restricted_title = $title;
$restricted_title =~ s/[^a-zA-Z]/_/g;
printf $summaryfile "%10s %s \n", $totalsize, $title;
}
return $totalsize;
}
sub usage {
print "Usage: $0 [FLAGS]\n\n";
print "FLAGS:\n";
print " -h\t\thelp\n";
print " -t TYPES\tSelect types to analyze (default = all)\n";
print " -l\t\tList available types\n";
print " -c\t\tPrint the configuration flags that would be used\n";
print " -D DIR\tSave data results to this directory\n";
print " -o FILE\tSave a complete summary chart to FILE\n";
print " -n\t\tDry run -- only show the commands to execute\n";
print " -j NUM\tExecute make with parallel building (-jNUM)\n";
print " -e\t\tUse exponential expansion (all combos) of the requested options\n";
print " -b NAME:NUM\tUse NAME and the NUM'th set as the base arguments to start from\n";
print " -T\t\tRun 'make test' at each step as well\n";
exit;
}
sub System {
my $file = shift;
my $num = shift;
my $title = shift;
my $pipe = " 2>&1 | tee $opts{'d'}/$num-$title.out\n";
print "### ", join(" ", @_), $pipe;
if (!$opts{'n'} && $file) {
print $file "### ", join(" ", @_), "\n";
}
if (!$opts{'n'}) {
system(join(" ", @_) . $pipe);
}
}