|
1 #!perl -w |
|
2 # |
|
3 # Copyright (c) 2009 Symbian Foundation Ltd |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of the License "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 # Symbian Foundation Ltd - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # Generate the BRAG-compatible XML summary of the Raptor log from Yarp analysis |
|
16 |
|
17 use strict; |
|
18 |
|
19 use Getopt::Long; |
|
20 use Text::CSV; |
|
21 |
|
22 |
|
23 if (!@ARGV) |
|
24 { |
|
25 warn "Generate an XML summary of the Raptor build from a Yarp CSV file\n"; |
|
26 warn "Eg: yarpToBRAG.pl aYarpFile.csv [*_yarp.csv ...]\n"; |
|
27 exit(1); |
|
28 } |
|
29 |
|
30 # Start to build structure to be output as XML (same format as XML::Parser would create for us) |
|
31 my $xmlNewline = bless { Text => "\n" }, "Characters"; |
|
32 my $buildPhase = bless { name => "Build", Kids => [ $xmlNewline ] }, "phase"; |
|
33 my $buildStatus = |
|
34 [ |
|
35 bless |
|
36 { |
|
37 Kids => |
|
38 [ |
|
39 $xmlNewline, |
|
40 $buildPhase, |
|
41 $xmlNewline, |
|
42 ] |
|
43 }, "buildStatus" |
|
44 ]; |
|
45 |
|
46 @ARGV = map { glob $_ } @ARGV; |
|
47 |
|
48 foreach my $yarpCSV (@ARGV) |
|
49 { |
|
50 # Read Yarp CSV File |
|
51 unless (open(CSV, $yarpCSV)) |
|
52 { |
|
53 warn "ERROR: Unable to open $yarpCSV to process. Skipping.\n"; |
|
54 next; |
|
55 } |
|
56 |
|
57 my $csv = Text::CSV->new(); |
|
58 my @keys = (); |
|
59 while (my $line = <CSV>) |
|
60 { |
|
61 chomp $line; |
|
62 |
|
63 unless ($csv->parse($line)) |
|
64 { |
|
65 my $err = $csv->error_input(); |
|
66 warn "WARNING: Failed to parse $yarpCSV line $. as CSV '$line': $err Skipping\n"; |
|
67 next; |
|
68 } |
|
69 |
|
70 if (!@keys) |
|
71 { |
|
72 @keys = $csv->fields(); |
|
73 next; |
|
74 } |
|
75 |
|
76 my @values = $csv->fields(); |
|
77 last unless $values[0]; |
|
78 unless (scalar @values == scalar @keys) |
|
79 { |
|
80 warn "WARNING: line does not match expected format at $yarpCSV line $.. Skipping\n"; |
|
81 next; |
|
82 } |
|
83 # Populate the hash using a hash slice |
|
84 my $failure = {}; |
|
85 @{$failure}{@keys} = @values; |
|
86 $failure->{platform} = lc $failure->{platform}; |
|
87 |
|
88 # Work out the package |
|
89 $failure->{package} = $failure->{bldinf}; |
|
90 $failure->{package} =~ s{[A-Z]:}{}i; |
|
91 $failure->{package} =~ s{^(/sf/.*?/.*?)/.*}{$1}i; |
|
92 |
|
93 # Create a more readable error message |
|
94 my %errorIdToDetail = ( |
|
95 tem => {message => "Failed to process $failure->{source}", severity => "major"}, |
|
96 msvctoolscompile => {message => "Failed to compile $failure->{source}", severity => "minor"}, |
|
97 compile => {message => "Failed to compile $failure->{source}", severity => "minor"}, |
|
98 compile2object => {message => "Failed to compile $failure->{source}", severity => "minor"}, |
|
99 win32compile2object => {message => "Failed to compile $failure->{source}", severity => "minor"}, |
|
100 tools2lib => {message => "Failed to build library $failure->{target}", severity => "minor"}, |
|
101 win32archive => {message => "Failed to build library $failure->{target}", severity => "minor"}, |
|
102 "link" => {message => "Failed to create symbols for $failure->{target}", severity => "minor"}, |
|
103 postlink => {message => "Failed to link $failure->{target}", severity => "minor"}, |
|
104 win32stageonelink => {message => "Failed to link $failure->{target} (stage 1)", severity => "minor"}, |
|
105 win32stagetwolink => {message => "Failed to link $failure->{target}", severity => "minor"}, |
|
106 win32simplelink => {message => "Failed to link $failure->{target}", severity => "minor"}, |
|
107 win32processexports => {message => "Failed to export $failure->{source} to $failure->{target}", severity => "minor"}, |
|
108 tracecompile => {message => "Trace compile failure for $failure->{target}", severity => "unknown"}, |
|
109 extension_makefile => {message => "Failed to process an extension makefile connected to $failure->{bldinf}", severity => "major"}, |
|
110 ); |
|
111 # die $failure->{name} unless exists $errorIdToDetail{$failure->{name}}; |
|
112 my $message = $errorIdToDetail{$failure->{name}}->{message} || "Unknown failure tag '$failure->{name}' ($failure->{source} -> $failure->{target})"; |
|
113 $failure->{severity} = $errorIdToDetail{$failure->{name}}->{severity} || "unknown"; |
|
114 |
|
115 # Look through the steps to see if we already have one to match this platform |
|
116 my $step; |
|
117 foreach (@{$buildPhase->{Kids}}) |
|
118 { |
|
119 next unless ref $_ eq "step"; |
|
120 if ($_->{name} eq $failure->{platform}) |
|
121 { |
|
122 $step = $_; |
|
123 last; |
|
124 } |
|
125 } |
|
126 unless ($step) |
|
127 { |
|
128 # First item found for this platform - create step entry |
|
129 $step = bless { name => $failure->{platform}, Kids => [ $xmlNewline ] }, "step"; |
|
130 push @{$buildPhase->{Kids}}, $step, $xmlNewline; |
|
131 # Also create empty <failures> tags with severities in a sensible order |
|
132 foreach my $severity (qw{critical major minor}) |
|
133 { |
|
134 my $failureSet = bless { level => $severity, Kids => [ $xmlNewline ] }, "failures"; |
|
135 push @{$step->{Kids}}, $failureSet, $xmlNewline; |
|
136 } |
|
137 } |
|
138 |
|
139 # Look through the sets of failures in this step to see if we hve one which matches this severity |
|
140 my $failureSet; |
|
141 foreach (@{$step->{Kids}}) |
|
142 { |
|
143 next unless ref $_ eq "failures"; |
|
144 if ($_->{level} eq $failure->{severity}) |
|
145 { |
|
146 $failureSet = $_; |
|
147 last; |
|
148 } |
|
149 } |
|
150 unless ($failureSet) |
|
151 { |
|
152 # First item found at this severity - create failures entry |
|
153 $failureSet = bless { level => $failure->{severity}, Kids => [ $xmlNewline ] }, "failures"; |
|
154 push @{$step->{Kids}}, $failureSet, $xmlNewline; |
|
155 } |
|
156 |
|
157 # Now create the failure itself, and add it to this failure set |
|
158 my $failureItem = bless { |
|
159 # href => "", |
|
160 "package" => $failure->{package}, |
|
161 Kids => [ bless { Text => $message }, "Characters" ], |
|
162 }, "failure"; |
|
163 push @{$failureSet->{Kids}}, $failureItem, $xmlNewline; |
|
164 } |
|
165 close(CSV); |
|
166 } |
|
167 # Print XML |
|
168 print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; |
|
169 print "<?xml-stylesheet type='text/xsl' href='brag.xsl'?>\n"; |
|
170 printTree($buildStatus->[0]); |
|
171 print "\n"; |
|
172 |
|
173 exit(0); |
|
174 |
|
175 sub printTree |
|
176 { |
|
177 my $tree = shift or die; |
|
178 die unless ref $tree; |
|
179 |
|
180 my $tagName = ref $tree; |
|
181 $tagName =~ s{^main::}{}; |
|
182 if ($tagName eq "Characters") |
|
183 { |
|
184 print $tree->{Text}; |
|
185 return; |
|
186 } |
|
187 |
|
188 print "<$tagName"; |
|
189 |
|
190 foreach my $attr ( |
|
191 sort { |
|
192 my $order = "name level start stop href"; |
|
193 my $ixA = index $order, $a; |
|
194 my $ixB = index $order, $b; |
|
195 die "$a $b" if $ixA + $ixB == -2; |
|
196 $ixA - $ixB; |
|
197 } |
|
198 grep { |
|
199 ! ref $tree->{$_} |
|
200 } |
|
201 keys %$tree) |
|
202 { |
|
203 print " $attr=\"$tree->{$attr}\""; |
|
204 } |
|
205 |
|
206 my $children = $tree->{Kids} || []; |
|
207 if (scalar @$children) |
|
208 { |
|
209 print ">"; |
|
210 foreach my $child (@$children) |
|
211 { |
|
212 printTree($child); |
|
213 } |
|
214 print "</$tagName"; |
|
215 } |
|
216 else |
|
217 { |
|
218 print "/" |
|
219 } |
|
220 |
|
221 print ">"; |
|
222 } |
|
223 |