|
1 #!perl |
|
2 # Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # Script to build specified MMP files with both command line and IDE, then |
|
16 # use EVALID to compare the results. |
|
17 # Inspired by "buildall.pl", written by Cuong Phan |
|
18 # |
|
19 # |
|
20 |
|
21 use strict; |
|
22 use File::Basename; # for fileparse() |
|
23 use File::Path; # for mkpath |
|
24 use Cwd; # for cwd |
|
25 use OLE; |
|
26 use Getopt::Long; |
|
27 |
|
28 sub Usage ($) |
|
29 { |
|
30 my ($message) = @_; |
|
31 print <<ENDHERESTRING; |
|
32 $message |
|
33 |
|
34 Usage : perl cw_ide_test.pl [-v] -f mmplist platform1 [platform2 ...] |
|
35 |
|
36 Builds specified MMP files with both the command line and the CodeWarrior IDE, |
|
37 storing the build products in zip files and comparing them with EVALID. |
|
38 The output can be summarised using scanlog.pl. |
|
39 |
|
40 All of the specified MMP files are build for all of the specified platforms. |
|
41 If -v is specified, the detailed build commands are included in the output. |
|
42 |
|
43 ENDHERESTRING |
|
44 |
|
45 exit 1; |
|
46 } |
|
47 |
|
48 my %Options=(); |
|
49 GetOptions(\%Options, "v", "f=s"); |
|
50 |
|
51 &Usage("No platforms specified") if (@ARGV < 1); |
|
52 &Usage("Must specify list of mmp files using -f") if (!defined($Options{"f"})); |
|
53 |
|
54 my @mmplist=(); |
|
55 my $specifiedCWD; |
|
56 open FILELIST, "<$Options{f}" or &Usage("Cannot open $Options{f}"); |
|
57 while (<FILELIST>) |
|
58 { |
|
59 $specifiedCWD = ""; |
|
60 |
|
61 if (/#.*cwd:/i) |
|
62 { |
|
63 $specifiedCWD = $_; |
|
64 $specifiedCWD =~ s/^.*cwd:/cwd:/i; |
|
65 $specifiedCWD =~ s/\).*$//; |
|
66 $specifiedCWD =~ s/\s*//g; |
|
67 $specifiedCWD =~ s/\//\\/g; |
|
68 $specifiedCWD .="?"; |
|
69 } |
|
70 |
|
71 s/#.*$//; # remove comments |
|
72 s/\s*$//; # remove trailing ws |
|
73 s/^\s*//; # remove leading ws |
|
74 s/\//\\/g; # convert / to \ |
|
75 next if ($_ eq ""); |
|
76 push @mmplist, $specifiedCWD.$_; |
|
77 } |
|
78 close FILELIST; |
|
79 |
|
80 &Usage("No MMP files?") if (@mmplist == 0); |
|
81 |
|
82 # create an instance of CodeWarrior |
|
83 my $CW = CreateObject OLE "CodeWarrior.CodeWarriorApp"; |
|
84 if (!defined($CW)) |
|
85 { |
|
86 print "Failed to start CodeWarrior\n"; |
|
87 exit(1); |
|
88 } |
|
89 |
|
90 # turn on autoflush, to get stdout in the right place... |
|
91 # These runes come from perlfaq5 |
|
92 |
|
93 my $old_fh = select(STDOUT); |
|
94 $| = 1; |
|
95 select($old_fh); |
|
96 |
|
97 foreach my $mmpfile (@mmplist) |
|
98 { |
|
99 $specifiedCWD = ""; |
|
100 |
|
101 if ($mmpfile =~ /^cwd:/) |
|
102 { |
|
103 $specifiedCWD = $mmpfile; |
|
104 $specifiedCWD =~ s/^cwd://; |
|
105 $specifiedCWD =~ s/\?.*$//; |
|
106 $mmpfile =~ s/^cwd:.*\?//; |
|
107 } |
|
108 |
|
109 if (!-f $mmpfile) |
|
110 { |
|
111 print "MISSING: $mmpfile\n"; |
|
112 next; |
|
113 } |
|
114 |
|
115 foreach my $platform (@ARGV) |
|
116 { |
|
117 $platform = uc $platform; |
|
118 my ($mmpname, $mmpdir, $mmpext) = fileparse($mmpfile,'\..*'); |
|
119 my $phasename = $mmpname."_".$platform; |
|
120 |
|
121 my $origdir = cwd; |
|
122 |
|
123 if ($specifiedCWD) |
|
124 { |
|
125 print ("chdir $specifiedCWD\n"); |
|
126 chdir ($specifiedCWD); |
|
127 |
|
128 # Workaround for Base components, where GENEXEC.MKE needs to be executed to export the required headers for a build |
|
129 do_system ("bldmake bldfiles"); |
|
130 do_system ("abld makefile $platform"); |
|
131 } |
|
132 else |
|
133 { |
|
134 print ("chdir $mmpdir\n"); |
|
135 chdir ($mmpdir); |
|
136 } |
|
137 |
|
138 my $time = localtime; |
|
139 print "===-------------------------------------------------\n"; |
|
140 print "=== $phasename\n"; |
|
141 print "===-------------------------------------------------\n"; |
|
142 print "=== $phasename started $time\n"; |
|
143 |
|
144 if ($specifiedCWD) |
|
145 { |
|
146 $mmpdir = "\\".$mmpdir; |
|
147 } |
|
148 else |
|
149 { |
|
150 $mmpdir = ""; |
|
151 } |
|
152 |
|
153 &do_one_mmp_file($phasename, $mmpname, $platform, $mmpdir); |
|
154 |
|
155 $time = localtime; |
|
156 print "=== $phasename finished $time\n"; |
|
157 |
|
158 chdir($origdir); |
|
159 print ("chdir $origdir\n"); |
|
160 } |
|
161 } |
|
162 |
|
163 $CW->Quit(0); |
|
164 exit(0); |
|
165 |
|
166 sub do_system($) |
|
167 { |
|
168 my ($cmd) = @_; |
|
169 print " $cmd\n"; |
|
170 return system($cmd); |
|
171 } |
|
172 |
|
173 sub zip_and_check($$$) |
|
174 { |
|
175 my ($zipname, $releaseref, $complain) = @_; |
|
176 |
|
177 unlink($zipname) if (-f $zipname); |
|
178 |
|
179 my @ziplist; |
|
180 foreach (sort keys %$releaseref) |
|
181 { |
|
182 if (-f $_) |
|
183 { |
|
184 push @ziplist,$_; # add to zip archive |
|
185 } |
|
186 else |
|
187 { |
|
188 print "MISSING: $_\n" if ($complain); |
|
189 } |
|
190 } |
|
191 |
|
192 if (scalar @ziplist ==0 && $complain) |
|
193 { |
|
194 print "Can't create empty archive $zipname\n"; |
|
195 return; |
|
196 } |
|
197 |
|
198 # Make the non-empty archive |
|
199 |
|
200 open ZIP, "| zip -q $zipname -@"; |
|
201 print ZIP |
|
202 join("\n",@ziplist,""); |
|
203 close ZIP; |
|
204 print "Created $zipname\n"; |
|
205 } |
|
206 |
|
207 sub do_one_mmp_file($$$) |
|
208 { |
|
209 my ($phasename, $mmpname, $platform, $mmpdir) = @_; |
|
210 |
|
211 print "=== $phasename == $mmpname.mmp\n"; |
|
212 |
|
213 # use MAKMAKE to generate the makefile |
|
214 # make CLEAN to remove any existing build results |
|
215 # make ALL to build everything |
|
216 # make WHAT to get the releaseables, as per abld.pl |
|
217 # check the releaseables and zip up the ones which do exist |
|
218 # make CLEAN again to get ready for the IDE build... |
|
219 |
|
220 my $makefile = "$mmpname.$platform"; |
|
221 my %allreleaseables=(); # complete list, for putting back afterwards |
|
222 my %releaseables=(); # just things we expect the IDE to build |
|
223 my %uncheckedreleaseables=(); |
|
224 my $makecmd = "make -s"; |
|
225 $makecmd = "make" if ($Options{"v"}); |
|
226 |
|
227 unlink $makefile if (-f $makefile); |
|
228 &do_system("perl -S makmake.pl $mmpdir$mmpname $platform"); |
|
229 return if (!-f $makefile); |
|
230 |
|
231 open PIPE,"make -s -r -f $makefile WHAT |"; |
|
232 while (<PIPE>) |
|
233 { |
|
234 next if (/Nothing to be done for \S+\.$/o); |
|
235 # releasables split on whitespace - quotes possible -stripped out |
|
236 while (/("([^"\t\n\r\f]+)"|([^ "\t\n\r\f]+))/go) |
|
237 { |
|
238 my $file = ($2 ? $2 : $3); |
|
239 $allreleaseables{$file}=1; |
|
240 next if ($file =~ /epoc32\\localisation\\/i); |
|
241 next if ($file =~ /epoc32\\data/i && $platform =~ /winscw/i); |
|
242 $releaseables{$file}=1; |
|
243 } |
|
244 } |
|
245 close PIPE; |
|
246 &zip_and_check("$mmpname.orig.$platform.zip", \%allreleaseables, 0); |
|
247 |
|
248 &do_system("$makecmd -r -f $makefile CLEAN"); |
|
249 &do_system("$makecmd -r -f $makefile ALL"); |
|
250 &zip_and_check("$mmpname.cmd.$platform.zip", \%releaseables, 1); |
|
251 |
|
252 &do_system("$makecmd -r -f $makefile CLEAN"); |
|
253 |
|
254 print "=== $phasename == $mmpname.mcp\n"; |
|
255 |
|
256 # Remove the remnants of previous projects |
|
257 # use MAKMAKE to generate the importable .xml |
|
258 # import the xml to create the .mcp |
|
259 # build the relevant targets |
|
260 # extract the contents of the "Errors & Warnings" window |
|
261 # check against the commandline list of releasables, zip up the ones which exist |
|
262 |
|
263 my $currentdir = cwd; |
|
264 $currentdir =~ s/\//\\/g; |
|
265 my $xmlfile = "$currentdir\\$mmpname.xml"; |
|
266 my $mcpfile = "$currentdir\\$mmpname.mcp"; |
|
267 my $mcpdata = "$currentdir\\${mmpname}_Data"; |
|
268 |
|
269 &do_system("rmdir /s/q $mcpdata") if (-d $mcpdata); |
|
270 unlink $mcpfile if (-f $mcpfile); |
|
271 unlink $xmlfile if (-f $xmlfile); |
|
272 |
|
273 &do_system("perl -S makmake.pl $mmpdir$mmpname CW_IDE:$platform"); |
|
274 if (-f $xmlfile) |
|
275 { |
|
276 &fixup_XML($xmlfile) if ($Options{"v"}); |
|
277 my $project = $CW->ImportProject($xmlfile, $mcpfile, 'true'); |
|
278 if (defined($project)) |
|
279 { |
|
280 my $success = &BuildTargets($project->Targets,$platform); |
|
281 $project->Close(); |
|
282 return if (!$success); |
|
283 &zip_and_check("$mmpname.ide.$platform.zip", \%releaseables, 1); |
|
284 } |
|
285 else |
|
286 { |
|
287 print "ERROR: failed to import $xmlfile\n"; |
|
288 return; |
|
289 } |
|
290 } |
|
291 else |
|
292 { |
|
293 print "ERROR: failed to create $xmlfile\n"; |
|
294 return; |
|
295 } |
|
296 |
|
297 print "=== $phasename == $mmpname.evalid\n"; |
|
298 |
|
299 # remove & recreate a clean temporary directory for unzipping |
|
300 # unzip the saved results of the cmd and ide builds |
|
301 # use EVALID to compare the releaseables |
|
302 |
|
303 my $evaliddir = "c:\\temp\\evalid"; |
|
304 &do_system("rmdir /s/q $evaliddir") if (-d $evaliddir); |
|
305 mkpath([$evaliddir]); |
|
306 |
|
307 if ( &do_system("unzip -q $mmpname.cmd.$platform.zip -d $evaliddir\\cmd")==0 |
|
308 && &do_system("unzip -q $mmpname.ide.$platform.zip -d $evaliddir\\ide")==0) |
|
309 { |
|
310 open EVALID,"perl -S evalid.pl $evaliddir\\ide $evaliddir\\cmd -c |"; |
|
311 while (<EVALID>) |
|
312 { |
|
313 print $_ if (/^(PROBLEM|Failed)/); |
|
314 print $_ if (/^OK/ && $Options{"v"}); |
|
315 if (/^FAILED/) |
|
316 { |
|
317 if (/\.map\t/i) |
|
318 { |
|
319 print "WARNING(S): $_"; |
|
320 } |
|
321 else |
|
322 { |
|
323 print "FATAL ERROR(S): $_"; |
|
324 } |
|
325 } |
|
326 } |
|
327 close EVALID; |
|
328 } |
|
329 else |
|
330 { |
|
331 print "FATAL ERROR(S): problems unpacking zip files\n"; |
|
332 } |
|
333 &do_system("rmdir /s/q $evaliddir") if (-d $evaliddir); |
|
334 |
|
335 # Restore original files, if any |
|
336 if (-e "$mmpname.orig.$platform.zip") |
|
337 { |
|
338 &do_system("unzip -q -o $mmpname.orig.$platform.zip -d \\"); |
|
339 } |
|
340 } |
|
341 |
|
342 sub fixup_XML($) |
|
343 { |
|
344 my ($xmlfile) = @_; |
|
345 open XML,"<$xmlfile" or return; |
|
346 my @lines = <XML>; |
|
347 close XML; |
|
348 |
|
349 foreach (@lines) |
|
350 { |
|
351 # Insist that build commands are logged to the output window, irrespective of CW version |
|
352 s-<SETTING><NAME>LogMessages</NAME><VALUE>false</VALUE></SETTING>-<SETTING><NAME>LogMessages</NAME><VALUE>true</VALUE></SETTING>-; |
|
353 s-<SETTING><NAME>ShowCommandLine</NAME><VALUE>false</VALUE></SETTING>-<SETTING><NAME>ShowCommandLine</NAME><VALUE>true</VALUE></SETTING>-; |
|
354 |
|
355 # Remove generation of Browse info by Language Parser (temporary workaround for crashes in automated IDE builds) |
|
356 s-<SETTING><NAME>BrowserGenerator</NAME><VALUE>2</VALUE></SETTING>-<SETTING><NAME>BrowserGenerator</NAME><VALUE>0</VALUE></SETTING>-; |
|
357 } |
|
358 |
|
359 open XML,">$xmlfile" or return; |
|
360 print XML @lines; |
|
361 close XML; |
|
362 } |
|
363 |
|
364 sub BuildTargets($$) |
|
365 { |
|
366 my ($targets,$platform) = @_; |
|
367 |
|
368 for (my $item=0; $item<$targets->Count; $item++ ) |
|
369 { |
|
370 my $target = $targets->Item($item); |
|
371 my $targetName = $target->name; |
|
372 # Skip platforms we aren't interested in... |
|
373 next if ($targetName !~ /$platform /i); |
|
374 |
|
375 print "Building $targetName...\n"; |
|
376 |
|
377 $target->RemoveObjectCode( 'true' ); |
|
378 |
|
379 my $buildMessages = $target->BuildAndWaitToComplete(); |
|
380 if (!defined($buildMessages)) |
|
381 { |
|
382 printf "FATAL ERROR(S): build aborted? (%s)\n", $target->LastError(); |
|
383 return 0; |
|
384 } |
|
385 |
|
386 my $messageList = $buildMessages->Informations; |
|
387 &printMessages("",$messageList) if defined($messageList); |
|
388 |
|
389 my $warningCount = $buildMessages->WarningCount; |
|
390 my $errorCount = $buildMessages->ErrorCount; |
|
391 print "Completed $targetName with $errorCount errors and $warningCount warnings\n"; |
|
392 |
|
393 if ($errorCount > 0) |
|
394 { |
|
395 $messageList = $buildMessages->Errors; |
|
396 &printMessages("FATAL ERROR(S): ", $messageList); |
|
397 } |
|
398 if ($warningCount > 0) |
|
399 { |
|
400 $messageList = $buildMessages->Warnings; |
|
401 &printMessages("WARNING: ", $messageList); |
|
402 } |
|
403 } |
|
404 return 1; |
|
405 } |
|
406 |
|
407 sub printMessages ($$) |
|
408 { |
|
409 my ($prefix,$messageList) = @_; |
|
410 |
|
411 # traverse through the list of messages |
|
412 for (my $item = 0; $item < ($messageList->Count); $item++) |
|
413 { |
|
414 my $message = $messageList->Item($item); |
|
415 print $prefix,$message->MessageText,"\n"; |
|
416 } |
|
417 } |
|
418 |