1#!/usr/bin/perl 2 3use strict; 4use Data::Dumper; 5use Getopt::Std; 6use IO::File; 7our %opts = (d => 'size-tests'); 8 9# default arguments go here 10my @sets = 11 ({ 12 "with-defaults" => '', 13 }); 14 15my %base_args = %{$sets[0]}; 16my ($basename, $basenum); 17 18getopts('t:hlcD:nj:o:eb:T', \%opts) || usage(); 19 20$opts{'j'} = "-j$opts{j}" if (exists($opts{'j'})); 21 22usage() if ($opts{'h'}); 23 24my @argumentsets = 25 ( 26 { 27 title => 'security-types', 28 arguments => 29 { 30 usm => { 31 'with-security-modules' => 'usm', 32 }, 33 dtlsandtls => { 34 'with-security-modules' => 'tsm', 35 'with-out-security-modules' => 'usm', 36 'with-transports' => 'DTLSUDP TLSTCP', 37 'with-mib-modules' => 'tlstm-mib tsm-mib' 38 }, 39 usmanddtlsandtls => { 40 'with-security-modules' => 'tsm usm', 41 'with-transports' => 'DTLSUDP TLSTCP', 42 'with-mib-modules' => 'tlstm-mib tsm-mib' 43 } 44 } 45 }, 46 { 47 title => 'minimalist', 48 arguments => 49 { 50 minimal => { 51 'enable-minimalist' => '', 52 }, 53 'not-minimal' => { 54 } 55 } 56 }, 57 { 58 title => 'mib-loading', 59 arguments => 60 { 61 'without-mib-loading' => { 62 'disable-mib-loading' => '', 63 }, 64 'with-mib-loading' => { 65 } 66 } 67 }, 68 { 69 title => 'debugging', 70 arguments => 71 { 72 'without-debugging' => { 73 'disable-debugging' => '', 74 }, 75 'with-debugging' => { 76 } 77 } 78 }, 79 { 80 title => 'logging', 81 arguments => 82 { 83 'without-logging' => { 84 'with-out-features' => 'logging', 85 }, 86 'with-logging' => { 87 } 88 } 89 }, 90 { 91 title => 'agent-mibs', 92 arguments => 93 { 94 'full-agent' => { 95 }, 96 'mini-agent' => { 97 'enable-mini-agent' => '', 98 } 99 } 100 }, 101 { 102 title => 'protocol-support', 103 arguments => 104 { 105 'everything' => { 106 }, 107 'read-only' => { 108 'enable-read-only' => '', 109 }, 110 'notify-only' => { 111 'enable-notify-only' => '', 112 } 113 } 114 }, 115 { 116 title => 'perl', 117 arguments => 118 { 119 'without-perl-modules' => { 120 'without-perl-modules' => '', 121 'disable-embedded-perl' => '', 122 }, 123 'with-perl-no-embedding' => { 124 'with-perl-modules' => '', 125 'disable-embedded-perl' => '', 126 }, 127 'with-perl-and-embedding' => { 128 'with-perl-modules' => '', 129 'enable-embedded-perl' => '', 130 } 131 } 132 }, 133 ); 134 135# map these to a referencable lookup hash 136my %argumentsets; 137foreach my $set (@argumentsets) { 138 $argumentsets{$set->{'title'}} = $set; 139} 140 141if ($opts{'l'}) { 142 print "Types available:\n"; 143 printf(" %-40.40s %s\n", "Test Title", "Number of subtests"); 144 printf(" %-40.40s %s\n", "-" x 39, "-" x length("Number of subtests")); 145 foreach my $type (@argumentsets) { 146 my @keys = keys(%{$type->{'arguments'}}); 147 printf(" %-40.40s %s\n", $type->{'title'}, $#keys+1); 148 } 149 exit; 150} 151 152my %types; 153if ($opts{'t'}) { 154 my @types = split(/,\s*/, $opts{'t'}); 155 foreach my $type (@types) { 156 $types{$type} = 1; 157 } 158} 159 160if ($opts{'b'}) { 161 # use this set as the base default set of arguments 162 ($basename, $basenum) = ($opts{'b'} =~ /(.*):(\d+)/); 163 if (!exists($argumentsets{$basename})) { 164 printf STDERR "failed to find set for -b argument: %s\n", $basename; 165 exit(1); 166 } 167 @sets = add_in_flags($argumentsets{$basename}, \%base_args, ()); 168 @sets = @sets[$basenum]; 169 %base_args = %{$sets[0]}; 170} 171 172foreach my $set (@argumentsets) { 173 if (!$opts{'t'} || exists($types{$set->{'title'}})) { 174 if ($basename && $set->{'title'} eq $basename) { 175 next; 176 } 177 @sets = add_in_flags($set, \%base_args, @sets); 178 } 179} 180 181if ($opts{'c'}) { 182 # print the configure flags 183 foreach my $set (@sets) { 184 print "$set->{'title'}:\n"; 185 print " ", generate_configure_flags($set), "\n"; 186 } 187 exit; 188} 189 190my $summaryfile; 191if ($opts{'o'} && !$opts{'n'}) { 192 $summaryfile = new IO::File; 193 $summaryfile->open(">$opts{o}"); 194} 195 196my $count = 0; 197foreach my $set (@sets) { 198 $count++; 199 build_set($count, $set); 200} 201 202sub add_in_flags { 203 my ($argumentset, $base_flags, @current_flags) = @_; 204 205 my @new_flags; 206 207 # do a linear search of the options 208 if (! $opts{'e'}) { 209 @new_flags = @current_flags; 210 foreach my $newargs (keys(%{$argumentset->{'arguments'}})) { 211 my %flags = %$base_flags; 212 213 $flags{'title'} = "$flags{'title'}:$newargs"; 214 215 foreach my $newflag (keys(%{$argumentset->{'arguments'}{$newargs}})) { 216 217 $flags{$newflag} .= " $argumentset->{'arguments'}{$newargs}{$newflag}"; 218 } 219 push @new_flags, \%flags; 220 } 221 return @new_flags; 222 } 223 224 # or an exponential search 225 foreach my $flags (@current_flags) { 226 foreach my $newargs (keys(%{$argumentset->{'arguments'}})) { 227 my %flags = %{$flags}; # copy the existing hash-set of flags 228 229 if (exists($flags{'title'})) { 230 $flags{'title'} .= ", $newargs"; 231 } else { 232 $flags{'title'} .= "$newargs"; 233 } 234 foreach my $newflag (keys(%{$argumentset->{'arguments'}{$newargs}})) { 235 236 $flags{$newflag} .= " $argumentset->{'arguments'}{$newargs}{$newflag}"; 237 } 238 239 push @new_flags, \%flags; 240 } 241 } 242 243 return @new_flags; 244} 245 246sub generate_configure_flags { 247 my ($arguments) = @_; 248 my $line = ""; 249 foreach my $arg (keys(%$arguments)) { 250 next if ($arg eq 'title'); 251 if ($arguments->{$arg} =~ /^\s*$/) { 252 $line .= " --$arg"; 253 } else { 254 $line .= " --$arg=\"$arguments->{$arg}\""; 255 } 256 } 257 return $line; 258} 259 260sub build_set { 261 my ($num, $arguments) = @_; 262 263 $num = sprintf("%03d", $num); 264 265 my $file; 266 267 if (!$opts{'n'}) { 268 mkdir $opts{'d'} if (! -d $opts{'d'}); 269 die "failed to create the $opts{'d'} directory" if (! -d $opts{'d'}); 270 271 $file = new IO::File; 272 $file->open(">$opts{'d'}/$num-0-cmd-summary"); 273 $file->print("Creating output for: $arguments->{'title'}\n"); 274 } 275 276 print "==================== $arguments->{'title'}\n"; 277 278 279 System ($file, $num, "1-distclean", "make distclean"); 280 System ($file, $num, "2-configure", 281 "./configure " . generate_configure_flags($arguments)); 282 System ($file, $num, "3-features", "make features"); 283 System ($file, $num, "4-make", "make $opts{'j'}"); 284 System ($file, $num, "5-unused-code", "perl local/minimalist/find-unused-code -g"); 285 System ($file, $num, "6-testing", "make -C testing test") if ($opts{'T'}); 286 287 if (!$opts{'n'}) { 288 analyze_size($arguments->{'title'}, "$opts{'d'}/$num-9-results"); 289 } 290} 291 292sub analyze_size { 293 my ($title, $filename) = @_; 294 295 my $outfile = new IO::File; 296 $outfile->open(">$filename"); 297 298 print "Results for: $title\n"; 299 printf $outfile "Results for: $title\n"; 300 printf ("%-50.50s %10s\n", "-" x 49, "-" x 10); 301 printf $outfile ("%-50.50s %10s\n", "-" x 49, "-" x 10); 302 303 my $totalsize = 0; 304 foreach my $buildfile (glob("snmplib/.libs/lib*.so.*.0.0"), 305 glob("agent/.libs/lib*.so.*.0.0"), 306 "agent/.libs/snmpd") { 307 308 my @info = stat($buildfile); 309 printf $outfile ("%-50.50s %10s\n", $buildfile, $info[7]); 310 printf("%-50.50s %10s\n", $buildfile, $info[7]); 311 $totalsize += $info[7]; 312 } 313 printf $outfile ("%-50.50s %10s\n", "-" x 49, "-" x 10); 314 printf $outfile ("%-50.50s %10s bytes\n", "TOTAL", $totalsize); 315 316 printf("%-50.50s %10s\n", "-" x 49, "-" x 10); 317 printf("%-50.50s %10s bytes\n", "TOTAL", $totalsize); 318 319 if (defined($summaryfile)) { 320 my $restricted_title = $title; 321 $restricted_title =~ s/[^a-zA-Z]/_/g; 322 printf $summaryfile "%10s %s \n", $totalsize, $title; 323 } 324 325 return $totalsize; 326} 327 328sub usage { 329 print "Usage: $0 [FLAGS]\n\n"; 330 print "FLAGS:\n"; 331 print " -h\t\thelp\n"; 332 print " -t TYPES\tSelect types to analyze (default = all)\n"; 333 print " -l\t\tList available types\n"; 334 print " -c\t\tPrint the configuration flags that would be used\n"; 335 print " -D DIR\tSave data results to this directory\n"; 336 print " -o FILE\tSave a complete summary chart to FILE\n"; 337 print " -n\t\tDry run -- only show the commands to execute\n"; 338 print " -j NUM\tExecute make with parallel building (-jNUM)\n"; 339 print " -e\t\tUse exponential expansion (all combos) of the requested options\n"; 340 print " -b NAME:NUM\tUse NAME and the NUM'th set as the base arguments to start from\n"; 341 print " -T\t\tRun 'make test' at each step as well\n"; 342 exit; 343} 344 345sub System { 346 my $file = shift; 347 my $num = shift; 348 my $title = shift; 349 my $pipe = " 2>&1 | tee $opts{'d'}/$num-$title.out\n"; 350 351 print "### ", join(" ", @_), $pipe; 352 if (!$opts{'n'} && $file) { 353 print $file "### ", join(" ", @_), "\n"; 354 } 355 356 if (!$opts{'n'}) { 357 system(join(" ", @_) . $pipe); 358 } 359} 360