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(); |
---|