| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | |
|---|
| 6 | # ---------------------------------------- |
|---|
| 7 | |
|---|
| 8 | my @shared = ( |
|---|
| 9 | 'AWT', |
|---|
| 10 | 'ARBDB', |
|---|
| 11 | 'CORE', |
|---|
| 12 | 'WINDOW', |
|---|
| 13 | ); |
|---|
| 14 | my %shared = map { $_ => 1; } @shared; |
|---|
| 15 | |
|---|
| 16 | # ---------------------------------------- |
|---|
| 17 | |
|---|
| 18 | my %dir2dirs = ( |
|---|
| 19 | |
|---|
| 20 | 'AISC' => 'NAMES_COM PROBE_COM', |
|---|
| 21 | 'AISC_COM' => 'AISC', |
|---|
| 22 | 'GL' => 'GL/glAW GL/glpng', |
|---|
| 23 | |
|---|
| 24 | ); |
|---|
| 25 | |
|---|
| 26 | my %dir2libs = ( |
|---|
| 27 | |
|---|
| 28 | 'NAMES_COM' => 'NAMES_COM/client.a NAMES_COM/common.a NAMES_COM/server.a', |
|---|
| 29 | 'PROBE_COM' => 'PROBE_COM/client.a PROBE_COM/common.a PROBE_COM/server.a', |
|---|
| 30 | 'GL/glAW' => 'GL/glAW/libglAW.a', |
|---|
| 31 | 'GL/glpng' => 'GL/glpng/libglpng_arb.a', |
|---|
| 32 | 'ptpan' => 'ptpan/PROBE.a', |
|---|
| 33 | |
|---|
| 34 | ); |
|---|
| 35 | |
|---|
| 36 | my %dir2targets = ( |
|---|
| 37 | |
|---|
| 38 | 'AISC_MKPTPS' => 'all', |
|---|
| 39 | 'bin' => 'all', |
|---|
| 40 | 'BINDEP' => 'all', |
|---|
| 41 | 'BUGEX' => 'all', |
|---|
| 42 | 'dep_graphs' => 'dep_graph', |
|---|
| 43 | 'GDE' => 'gde', |
|---|
| 44 | 'GDEHELP' => 'help menus', |
|---|
| 45 | 'HELP_SOURCE' => 'help', |
|---|
| 46 | 'INCLUDE' => 'all', |
|---|
| 47 | 'lib' => 'help libs perl', |
|---|
| 48 | 'PERL2ARB' => 'perl', |
|---|
| 49 | 'PERL_SCRIPTS' => 'testperlscripts', |
|---|
| 50 | 'PROBE_SET' => 'pst', |
|---|
| 51 | 'READSEQ' => 'readseq', |
|---|
| 52 | 'SL' => 'all', |
|---|
| 53 | 'SOURCE_TOOLS' => 'links valgrind_update', |
|---|
| 54 | 'TEMPLATES' => 'all', |
|---|
| 55 | 'TOOLS' => 'tools', |
|---|
| 56 | 'UNIT_TESTER' => 'ut', |
|---|
| 57 | |
|---|
| 58 | ); |
|---|
| 59 | |
|---|
| 60 | # ---------------------------------------- |
|---|
| 61 | |
|---|
| 62 | my $ARBHOME = $ENV{ARBHOME}; |
|---|
| 63 | if ((not defined $ARBHOME) or (not -d $ARBHOME)) { |
|---|
| 64 | die "Need correct \$ARBHOME"; |
|---|
| 65 | } |
|---|
| 66 | my $SOURCE_TOOLS = $ARBHOME.'/SOURCE_TOOLS'; |
|---|
| 67 | |
|---|
| 68 | sub dir2name($$$) { |
|---|
| 69 | my ($dir,$prefix,$suffix) = @_; |
|---|
| 70 | |
|---|
| 71 | if ($dir eq '') { return undef; } |
|---|
| 72 | |
|---|
| 73 | my $lastname = $dir; |
|---|
| 74 | if ($dir =~ /\/([^\/]+)$/) { $lastname = $1; } |
|---|
| 75 | |
|---|
| 76 | my $useddir = ($suffix eq '.so') ? 'lib' : $dir; |
|---|
| 77 | my $name = $useddir.'/'.$prefix.$lastname.$suffix; |
|---|
| 78 | |
|---|
| 79 | return $name; |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | sub dirs2changedlibs($); |
|---|
| 83 | sub dirs2changedlibs($) { |
|---|
| 84 | my ($dirs) = @_; |
|---|
| 85 | |
|---|
| 86 | my @dir = split / /,$dirs; |
|---|
| 87 | my %libs = (); |
|---|
| 88 | |
|---|
| 89 | foreach my $dir (@dir) { |
|---|
| 90 | if (defined $dir2dirs{$dir}) { |
|---|
| 91 | my $dirs2 = $dir2dirs{$dir}; |
|---|
| 92 | my $libs2 = dirs2changedlibs($dirs2); |
|---|
| 93 | foreach (split / /,$libs2) { $libs{$_} = 1; } |
|---|
| 94 | } |
|---|
| 95 | elsif (defined $dir2libs{$dir}) { |
|---|
| 96 | my $libs = $dir2libs{$dir}; |
|---|
| 97 | foreach (split / /,$libs) { $libs{$_} = 1; } |
|---|
| 98 | } |
|---|
| 99 | else { |
|---|
| 100 | my $prefix = ''; |
|---|
| 101 | my $suffix = '.a'; |
|---|
| 102 | |
|---|
| 103 | if (defined $shared{$dir}) { |
|---|
| 104 | $prefix = 'lib'; |
|---|
| 105 | $suffix = '.so'; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | my $libname = dir2name($dir,$prefix,$suffix); |
|---|
| 109 | $libs{$libname} = 1; |
|---|
| 110 | } |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | return join(' ',keys %libs); |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | sub changedlibs2targets($) { |
|---|
| 117 | my ($changed_lib) = @_; |
|---|
| 118 | |
|---|
| 119 | my %targets = (); |
|---|
| 120 | foreach (split / /,$changed_lib) { |
|---|
| 121 | # all client.a and common.a libs are identical (the libs in PROBE_COM are used in dependencies) |
|---|
| 122 | if ($_ eq 'NAMES_COM/client.a') { $_ = 'PROBE_COM/client.a'; } |
|---|
| 123 | if ($_ eq 'NAMES_COM/common.a') { $_ = 'PROBE_COM/common.a'; } |
|---|
| 124 | |
|---|
| 125 | my $cmd = $SOURCE_TOOLS.'/needed_libs.pl -F -U -I -T '.$_; |
|---|
| 126 | my $base_targets = `$cmd`; |
|---|
| 127 | chomp($base_targets); |
|---|
| 128 | foreach (split / /,$base_targets) { $targets{$_} = 1; } |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | # modify targets |
|---|
| 132 | my @targets = map { |
|---|
| 133 | if ($_ =~ /\//) { |
|---|
| 134 | if ($_ =~ /\.a$/o) { |
|---|
| 135 | $`.'.dummy'; |
|---|
| 136 | } |
|---|
| 137 | elsif ($_ =~ /\/([^\/]+)\.o$/o) { |
|---|
| 138 | my $dir = $`; |
|---|
| 139 | dir2name($dir,'','.dummy'); |
|---|
| 140 | } |
|---|
| 141 | else { |
|---|
| 142 | $_; |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | else { |
|---|
| 146 | 'rac_'.$_; |
|---|
| 147 | } |
|---|
| 148 | } keys %targets; |
|---|
| 149 | |
|---|
| 150 | return(join(' ', @targets)); |
|---|
| 151 | } |
|---|
| 152 | |
|---|
| 153 | sub dirs2targets($) { |
|---|
| 154 | my ($dirs) = @_; |
|---|
| 155 | my %targets = (); |
|---|
| 156 | foreach (split / /,$dirs) { |
|---|
| 157 | if (defined $dir2targets{$_}) { |
|---|
| 158 | my $targets = $dir2targets{$_}; |
|---|
| 159 | foreach (split / /,$targets) { $targets{$_} = 1; } |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | return join(' ',keys %targets); |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | sub config2env() { |
|---|
| 166 | my $conf = $ARBHOME.'/config.makefile'; |
|---|
| 167 | |
|---|
| 168 | if (not -f $conf) { |
|---|
| 169 | print "$conf not found.. generating\n"; |
|---|
| 170 | my $cmd = "cd $ARBHOME;make"; |
|---|
| 171 | system($cmd); |
|---|
| 172 | exit(1); |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | open(CONF,'<'.$conf) || die "can't read '$conf' (Reason: $!)"; |
|---|
| 176 | |
|---|
| 177 | my $OPENGL = 0; |
|---|
| 178 | my $UNIT_TESTS = 0; |
|---|
| 179 | |
|---|
| 180 | foreach (<CONF>) { |
|---|
| 181 | chomp; |
|---|
| 182 | if (/^OPENGL\s*:=\s*([0-9]+)/) { $OPENGL = $1; } |
|---|
| 183 | if (/^UNIT_TESTS\s*:=\s*([0-9]+)/) { $UNIT_TESTS = $1; } |
|---|
| 184 | } |
|---|
| 185 | close(CONF); |
|---|
| 186 | |
|---|
| 187 | print "Using:\n"; |
|---|
| 188 | print "- OPENGL=$OPENGL\n"; |
|---|
| 189 | print "- UNIT_TESTS=$UNIT_TESTS\n"; |
|---|
| 190 | |
|---|
| 191 | if ($OPENGL==1) { |
|---|
| 192 | $ENV{RNA3D_LIB} = 'RNA3D/RNA3D.a'; |
|---|
| 193 | } |
|---|
| 194 | |
|---|
| 195 | return $UNIT_TESTS; |
|---|
| 196 | } |
|---|
| 197 | |
|---|
| 198 | sub dump_log($) { |
|---|
| 199 | my ($log) = @_; |
|---|
| 200 | print "---------------------------------------- [$log start]\n"; |
|---|
| 201 | open(LOG,'<'.$log) || die "can't read '$log' (Reason: $!)"; |
|---|
| 202 | print <LOG>; |
|---|
| 203 | close(LOG); |
|---|
| 204 | print "---------------------------------------- [$log end]\n"; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | sub system_no_error_or_die($) { |
|---|
| 208 | my ($cmd) = @_; |
|---|
| 209 | if (system($cmd)!=0) { die "could not execute '$cmd'"; } |
|---|
| 210 | if ($? == -1) { die "could not execute '$cmd'"; } |
|---|
| 211 | if ($? & 127) { die sprintf("child died with signal %d", ($? & 127)); } |
|---|
| 212 | my $exitcode = ($? >> 8); |
|---|
| 213 | if ($exitcode!=0) { die "command '$cmd' failed (exitcode=$exitcode)"; } |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | sub main() { |
|---|
| 217 | my $dir = `pwd`; |
|---|
| 218 | chomp($dir); |
|---|
| 219 | |
|---|
| 220 | if (not defined $ENV{LINK_STATIC}) { |
|---|
| 221 | print "Warning: LINK_STATIC not defined (assuming 0 - which is wrong for OSX)\n"; |
|---|
| 222 | $ENV{LINK_STATIC} = '0'; # wrong for OSX |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | my $UNIT_TESTS = config2env(); |
|---|
| 226 | |
|---|
| 227 | if (not $dir =~ /^$ARBHOME/) { |
|---|
| 228 | print "Usage: simply call in any directory inside ARBHOME\n"; |
|---|
| 229 | print "It will assume you changed something there and remake all depending executables\n"; |
|---|
| 230 | print "(In fact this is a lie, it won't work everywhere:)\n"; |
|---|
| 231 | |
|---|
| 232 | die "Not called from inside $ARBHOME"; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | print "remake[3]: Entering directory `$ARBHOME'\n"; |
|---|
| 236 | chdir($ARBHOME); |
|---|
| 237 | |
|---|
| 238 | $dir = $'; |
|---|
| 239 | $dir =~ s/^\///; |
|---|
| 240 | |
|---|
| 241 | my $changed_libs = dirs2changedlibs($dir); |
|---|
| 242 | my $targets; |
|---|
| 243 | if ($changed_libs eq '') { |
|---|
| 244 | print "Called in ARBHOME\n"; |
|---|
| 245 | $targets = 'all'; |
|---|
| 246 | } |
|---|
| 247 | else { |
|---|
| 248 | $targets = ''; |
|---|
| 249 | while ($targets eq '') { |
|---|
| 250 | print "Assuming $changed_libs changed\n"; |
|---|
| 251 | $targets = changedlibs2targets($changed_libs); |
|---|
| 252 | if ($targets eq '') { $targets = dirs2targets($dir); } |
|---|
| 253 | |
|---|
| 254 | if ($targets eq '') { |
|---|
| 255 | if ($dir =~ /\//) { |
|---|
| 256 | my $updir = $`; |
|---|
| 257 | print "No known targets for $dir - trying $updir\n"; |
|---|
| 258 | $dir = $updir; |
|---|
| 259 | $changed_libs = dirs2changedlibs($dir); |
|---|
| 260 | } |
|---|
| 261 | else { |
|---|
| 262 | die "No idea what to remake for '$dir'\n "; |
|---|
| 263 | } |
|---|
| 264 | } |
|---|
| 265 | } |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | if ($targets ne '') { |
|---|
| 269 | my $cores = `cat /proc/cpuinfo | grep processor | wc -l`; |
|---|
| 270 | if ($cores<1) { $cores = 1; } |
|---|
| 271 | my $jobs = $cores+1; |
|---|
| 272 | print "Remaking\n"; |
|---|
| 273 | |
|---|
| 274 | foreach (split / /,$targets) { print " - $_\n"; } |
|---|
| 275 | |
|---|
| 276 | print "\n"; |
|---|
| 277 | |
|---|
| 278 | my $premake = "make -j$jobs up_by_remake"; |
|---|
| 279 | print "Silent premake: '$premake'\n"; |
|---|
| 280 | my $log = 'silent_premake.log'; |
|---|
| 281 | $premake = "cd $ARBHOME;$premake > $log 2>&1"; |
|---|
| 282 | print "Silent premake: '$premake' (real)\n"; |
|---|
| 283 | |
|---|
| 284 | eval { |
|---|
| 285 | system_no_error_or_die($premake); |
|---|
| 286 | }; |
|---|
| 287 | if ($@) { |
|---|
| 288 | my $err = "Silent premake failed (".$@.")"; |
|---|
| 289 | # print "\nError: $err\n"; (too common. spams compile log. also printed below) |
|---|
| 290 | dump_log($log); |
|---|
| 291 | die $err; |
|---|
| 292 | } |
|---|
| 293 | else { |
|---|
| 294 | open(LOG,'<'.$log) || die "can't read '$log' (Reason: $!)"; |
|---|
| 295 | my @warnings = grep /:\swarning:\s/, <LOG>; |
|---|
| 296 | close(LOG); |
|---|
| 297 | if (scalar(@warnings)) { |
|---|
| 298 | print "\nWarnings detected:\n"; |
|---|
| 299 | dump_log($log); |
|---|
| 300 | } |
|---|
| 301 | } |
|---|
| 302 | print "\n"; |
|---|
| 303 | |
|---|
| 304 | my $targets_contain_unittests = 0; |
|---|
| 305 | my $targets_are_timed = 0; |
|---|
| 306 | |
|---|
| 307 | my %targets = map { $_ => 1; } split / /,$targets; |
|---|
| 308 | if (defined $targets{all}) { |
|---|
| 309 | $targets_contain_unittests = 1; |
|---|
| 310 | $targets_are_timed = 1; |
|---|
| 311 | } |
|---|
| 312 | if (defined $targets{ut}) { |
|---|
| 313 | $targets_contain_unittests = 1; |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | my $makecmd; |
|---|
| 317 | my $makeFlags = " -j$jobs --warn-undefined-variables"; # warn about undefined makefile variables |
|---|
| 318 | # these variables are known to be undefined: |
|---|
| 319 | $ENV{WITHPERL} = ''; |
|---|
| 320 | $ENV{TIMED_TARGET} = ''; |
|---|
| 321 | $ENV{ONE_TIMED_TARGET} = ''; |
|---|
| 322 | |
|---|
| 323 | if ($targets_are_timed==1) { |
|---|
| 324 | $makecmd = "cd $ARBHOME;make $makeFlags $targets"; |
|---|
| 325 | } |
|---|
| 326 | else { |
|---|
| 327 | my $timed_target = (($UNIT_TESTS==0) or ($targets_contain_unittests==1)) ? 'timed_target' : 'timed_target_tested'; |
|---|
| 328 | $makecmd = "cd $ARBHOME;make \"TIMED_TARGET=$targets\" $makeFlags $timed_target"; |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | print "[Make: '$makecmd']\n"; |
|---|
| 332 | system($makecmd)==0 || die "error executing '$makecmd' (exitcode=$?)\n"; |
|---|
| 333 | print "remake[3]: Leaving directory `$ARBHOME'\n"; |
|---|
| 334 | |
|---|
| 335 | unlink($log); |
|---|
| 336 | } |
|---|
| 337 | } |
|---|
| 338 | |
|---|
| 339 | main(); |
|---|