pytest is not correctly auto-installed
[WebKit-https.git] / Tools / Scripts / filter-build-webkit
1 #!/usr/bin/env perl
2
3 # Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
4
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 # 1.  Redistributions of source code must retain the above copyright
9 #     notice, this list of conditions and the following disclaimer.
10 # 2.  Redistributions in binary form must reproduce the above copyright
11 #     notice, this list of conditions and the following disclaimer in the
12 #     documentation and/or other materials provided with the distribution.
13
14 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
15 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25 # Filters the output of build-webkit into a more human-readable format.
26
27 use strict;
28 use warnings;
29
30 use CGI qw(escapeHTML);
31 use File::Basename;
32 use FindBin;
33 use lib $FindBin::Bin;
34 use Getopt::Long;
35 use VCSUtils;
36
37 use constant {
38     STYLE_PLAIN => 0,
39     STYLE_HEADER => 1,
40     STYLE_SUCCESS => 2,
41     STYLE_ALERT => 3,
42
43     HTML_HEADER =><<HTMLHEADER,
44 <html>
45     <head>
46         <title>Build Log</title>
47         <style>
48             body { font-family: Monaco, monospace; font-size: 10px; color: #666; line-height: 1.5em; }
49             h2 { margin: 1.5em 0 0 0; font-size: 1.0em; font-weight: bold; color: blue; }
50             p { margin: 0; padding-left: 1.5em; border-left: 3px solid #fff; }
51             p.alert { border-left-color: red; color: red; margin: 1.5em 0 0 0; }
52             p.alert + p { margin: 1.5em 0 0 0; }
53             p.alert + p.alert { margin: 0; }
54             p.success { color: green; }
55         </style>
56     </head>
57     <body>
58 HTMLHEADER
59
60     HTML_FOOTER =><<HTMLFOOTER,
61     </body>
62 </html>
63 HTMLFOOTER
64 };
65
66 sub printLine($$);
67 sub setLogfileOption($$);
68 sub setOutputFormatOption($$);
69 sub shouldIgnoreLine($$);
70 sub usageAndExit();
71
72 # Defined in VCSUtils.
73 sub possiblyColored($$);
74
75 # Global variables used only in global scope.
76 my $outputPath = "&STDOUT";
77 my $platform = "mac";
78 my $showHelp;
79
80 # Global variables used in global and subroutine scope.
81 our $logUnfilteredOutput;
82 our $outputFormat = "text";
83 our $unfilteredOutputPath = "build.log";
84 our $useColor = -t STDOUT;
85
86 sub usageAndExit()
87 {
88     print STDERR <<__END__;
89 Usage: @{[ basename($0) ]} [options] buildlog1 [buildlog2 ...]
90        build-webkit | @{[ basename($0) ]} [options]
91   -h|--help     Show this help message
92   -p|--platform Logfile type (default: $platform)
93 Output Options:
94   -o|--output   Path for output (default: STDOUT)
95   -f|--format   Output format (default: $outputFormat)
96                   text: Plain text
97                   html: Standalone HTML document
98   --[no-]color  ANSI color output for text (default: on, if -o is STDOUT)
99 Unfiltered Logging Options:
100   -l|--log      Save unfiltered output to file (see --log-file)
101   --logfile     Path to save unfiltered output (implies --log, default: $unfilteredOutputPath)
102 __END__
103     exit 1;
104 }
105
106 my $getOptionsResult = GetOptions(
107     'h|help'                => \$showHelp,
108     'o|output=s'            => \$outputPath,
109     'p|platform=s'          => \$platform,
110     'f|format=s'            => \&setOutputFormatOption,
111     'color!'                => \$useColor,
112     'l|log'                 => \$logUnfilteredOutput,
113     'logfile=s'             => \&setLogfileOption,
114 );
115
116 if (-t STDIN || $showHelp || !$getOptionsResult) {
117     usageAndExit();
118 }
119
120 open(OUTPUT_HANDLE, ">$outputPath") or die "Failed to open $outputPath : $!";
121 if ($logUnfilteredOutput) {
122     open(UNFILTERED_OUTPUT_HANDLE, ">$unfilteredOutputPath") or die "Failed to open $unfilteredOutputPath : $!";
123 }
124
125 print OUTPUT_HANDLE HTML_HEADER if ($outputFormat eq "html");
126
127 my $buildFinished;
128 my $buildFailed = 0;
129 for (my $previousLine = "", my $line = <>; $line; $previousLine = $line, $line = <>) {
130     print UNFILTERED_OUTPUT_HANDLE $line if $logUnfilteredOutput;
131
132     chomp($line);
133
134     next if shouldIgnoreLine($previousLine, $line);
135
136     if ($line =~ /^={10}/) {
137         printLine($line, STYLE_SUCCESS);
138         $buildFinished = 1;
139     } elsif ($line =~ /^===/) {
140         printLine($line, STYLE_HEADER);
141     } elsif ($line =~ /Checking Dependencies|Check dependencies|Create product structure|Write auxiliary files|LinkStoryboards/) {
142         printLine($line, STYLE_PLAIN);
143     } elsif ($line =~ /\*\* BUILD SUCCEEDED \*\*/) {
144         printLine("Build Succeeded", STYLE_SUCCESS);
145     } elsif ($line =~ /^(\e\[1m)?(PhaseScriptExecution|ClCompile|CompileC|Distributed-CompileC|Ld|PBXCp|CpResource|CopyPNGFile|CopyTiffFile|CpHeader|Preprocess|Processing|ProcessInfoPlistFile|ProcessPCH|ProcessPCH\+\+|Touch|Libtool|CopyStringsFile|Mig|CreateUniversalBinary|Analyze|AnalyzeShallow|ProcessProductPackaging|CodeSign|Validate|SymLink|Updating|CompileDTraceScript|CompileXIB|StripNIB|CopyPlistFile|GenerateDSYMFile|GenerateTAPI|CompileStoryboard|ExternalBuildToolExecution)(\e\[0m)? ("[^"]+"|(\\|(?<=\\)\s|\S)+)?/) {
146         my ($command, $path) = ($2, basename($4));
147         $path =~ s/("|\\|\.[ah]$)//g;
148         printLine("$command $path", STYLE_PLAIN);
149     } elsif ($line =~ /^\S+mkdir .*?(\S+)$/) {
150         my $path = basename($1);
151         printLine("mkdir $path", STYLE_PLAIN);
152     } elsif ($line =~ /^cp (\S+)/) {
153         my $path = basename($1);
154         printLine("cp $path", STYLE_PLAIN);
155     } elsif ($line =~ /python (\S+\.py) (\S+)/) {
156         my ($command, $path) = (basename($1), basename($2));
157         printLine("python $command $path", STYLE_PLAIN);
158     } elsif ($line =~ /^\/\S+?(strip|WebCoreExportFileGenerator) .*?(\/|\> )(\S+)/) {
159         my ($command, $path) = (basename($1), basename($3));
160         printLine("$command $path", STYLE_PLAIN);
161     } elsif ($line =~ /^offlineasm\: /) {
162         printLine($line, STYLE_PLAIN);
163     } elsif ($line =~ /^Generating (\S+) from (\S+)/) {
164         printLine($line, STYLE_PLAIN);
165     } elsif ($line =~ /^Generating bindings for the (\S+) builtin\./) {
166         printLine("Generating $1 builtin", STYLE_PLAIN);
167     } elsif ($line =~ /^Generating (bindings|messages? (header|receiver|dispatcher)|derived source) for (\S+)\.\.\./) {
168         my ($command, $path) = ($1, basename($3));
169         printLine("Generating $command $path", STYLE_PLAIN);
170     } elsif ($line =~ /^Pre-processing (\S+) sandbox profile/) {
171         printLine($line, STYLE_PLAIN);
172     } elsif ($line =~ /^(\S+\/cc).*?(\S+)\.(out|exp)/) {
173         my ($command, $path) = (basename($1), basename($2));
174         printLine("$command $path", STYLE_PLAIN);
175     } else {
176         # This only gets hit if stderr is redirected to stdout.
177         if (($line =~ /\*\* BUILD FAILED \*\*/) || ($line =~ /^Build FAILED./)) {
178             $buildFailed = 1;
179         }
180         printLine($line, $buildFinished ? STYLE_SUCCESS : STYLE_ALERT);
181     }
182 }
183
184 print OUTPUT_HANDLE HTML_FOOTER if ($outputFormat eq "html");
185
186 close(OUTPUT_HANDLE);
187 close(UNFILTERED_OUTPUT_HANDLE) if ($logUnfilteredOutput);
188
189 exit $buildFailed;
190
191 sub printLine($$)
192 {
193     my ($line, $style) = @_;
194
195     if ($outputFormat eq "html") {
196         $line = escapeHTML($line);
197         if    ($style == STYLE_HEADER)  { print OUTPUT_HANDLE "<h2>$line</h2>"; }
198         elsif ($style == STYLE_SUCCESS) { print OUTPUT_HANDLE "<p class=\"success\">$line</p>"; }
199         elsif ($style == STYLE_ALERT)   { print OUTPUT_HANDLE "<p class=\"alert\">$line</p>"; }
200         else                            { print OUTPUT_HANDLE "<p>$line</p>"; }
201     } else {
202         if ($useColor) {
203             my $colors = "reset";
204             if ($style == STYLE_HEADER)  { $colors = "blue"; }
205             if ($style == STYLE_SUCCESS) { $colors = "green"; }
206             if ($style == STYLE_ALERT)   { $colors = "red"; }
207             print OUTPUT_HANDLE possiblyColored($colors, $line);
208         } else {
209             print OUTPUT_HANDLE $line;
210         }
211     }
212     print OUTPUT_HANDLE "\n";
213 }
214
215 sub setLogfileOption($$)
216 {
217     my ($opt, $value) = @_;
218     $unfilteredOutputPath = $value;
219     $logUnfilteredOutput = 1;
220 }
221
222 sub setOutputFormatOption($$)
223 {
224     my ($opt, $value) = @_;
225     $value = lc($value);
226     if ($value ne "html" && $value ne "text") {
227         die "The $opt option must be either \"html\" or \"text\"";
228     }
229     $outputFormat = $value;
230 }
231
232 sub shouldShowSubsequentLine($)
233 {
234     my ($line) = @_;
235
236     return 1 if $line =~ /referenced from:$/;
237     return 1 if $line =~ /(note:|error:)/;
238     
239     return 0;
240 }
241
242 sub shouldIgnoreLine($$)
243 {
244     my ($previousLine, $line) = @_;
245
246     return 1 if $line =~ /^\s*$/;
247     return 1 if $line =~ /^Build settings from command line:/;
248     return 1 if $line =~ /make(\[\d+\])?: Nothing to be done for `all'\./;
249     return 1 if $line =~ /^JavaScriptCore\/create_hash_table/;
250     return 1 if $line =~ /JavaScriptCore.framework\/PrivateHeaders\/create_hash_table/;
251     return 1 if $line =~ /^JavaScriptCore\/pcre\/dftables/;
252     return 1 if $line =~ /^Creating hashtable for /;
253     return 1 if $line =~ /^Wrote output to /;
254     return 1 if $line =~ /^UNDOCUMENTED: /;
255     return 1 if $line =~ /libtool.*has no symbols/;
256     return 1 if $line =~ /^# Lower case all the values, as CSS values are case-insensitive$/;
257     return 1 if $line =~ /^if sort /;
258     return 1 if $line =~ /set-webkit-configuration/;
259     return 1 if $line =~ /^building file list/;
260     return 1 if $line =~ /^\.\/$/;
261     return 1 if $line =~ /^\S+\.h$/;
262     return 1 if $line =~ /^\S+\/$/;
263     return 1 if $line =~ /^sent \d+ bytes/;
264     return 1 if $line =~ /^total size is/;
265     return 1 if $line =~ /^\( (xcodebuild|if) /;
266     return 1 if $line =~ /^warning\: detected internal install, passing entitlements to simulator anyway\./;
267     return 1 if $line =~ /may not function in the Simulator because Ad Hoc/;
268     return 1 if $line =~ /\/usr\/bin\/clang .*? \> \S+.sb/;
269     return 1 if $line =~ / xcodebuild\[[0-9]+:[0-9a-f]+\]\s+DVTAssertions: Warning in .*XCClangResultsPostprocessor.m/;
270     return 1 if $line =~ /^(Details|Object|Method|Function|Thread):/;
271     return 1 if $line =~ /^Please file a bug at /;
272     return 1 if $line =~ /created by an unsupported XCDependencyGraph build$/;
273
274     if ($platform eq "win") {
275         return 1 if $line =~ /^\s*(touch|perl|cat|rm -f|del|python|\/usr\/bin\/g\+\+|gperf|echo|sed|if \[ \-f|WebCore\/generate-export-file) /;
276         return 1 if $line =~ /^\s*(if not exist \"|if errorlevel 1)/;
277         return 1 if $line =~ /(^\s*|MSB3073:\s+)(set |REM |cmd \/c)/;
278         return 1 if $line =~ /^\s*[cC]:\\[pP]rogram [fF]iles.*\\.*\\(CL|midl)\.exe /;
279         return 1 if $line =~ /^\s*Processing .*\.(acf|h|idl)\s*$/;
280         return 1 if $line =~ /^\s*printf /;
281         return 1 if $line =~ /^\s*\/usr\/bin\/bash\s*/;
282         return 1 if $line =~ /^\s*offlineasm: Nothing changed/;
283         return 1 if $line =~ / \d+ File\(s\) copied/;
284         return 1 if $line =~ /^\s*File not found - \*\.h/;
285         return 1 if $line =~ /mkdir\s+\"/;
286         return 1 if $line =~ /xcopy \/y \/d \"/;
287         return 1 if $line =~ /\.obj\"\s*$/;
288         return 1 if $line =~ /:\s+(cmd \/c|set)\s+/;
289         return 1 if $line =~ /MSB3073:\s+$/;
290         return 1 if $line =~ /MSB3073:\s+if not exist/;
291         return 1 if $line =~ /which.exe bash/;
292     } else {
293         return 1 if $line =~ /^(touch|perl|cat|rm -f|python|\/usr\/bin\/g\+\+|\/bin\/ln|gperf|echo|sed|if \[ \-f|WebCore\/generate-export-file|write-file|chmod) /;
294         return 1 if $line =~ /^    / && !shouldShowSubsequentLine($previousLine);
295         return 1 if $line =~ /^printf /;
296         return 1 if $line =~ /^offlineasm: Nothing changed/;
297     }
298     return 1 if $line =~ /^Showing first/;
299
300     return 0;
301 }