3 # Copyright (C) 2011 Apple Inc. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
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.
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.
25 # Filters the output of build-webkit into a more human-readable format.
30 use CGI qw(escapeHTML);
33 use lib $FindBin::Bin;
43 HTML_HEADER =><<HTMLHEADER,
46 <title>Build Log</title>
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; }
60 HTML_FOOTER =><<HTMLFOOTER,
67 sub setLogfileOption($$);
68 sub setOutputFormatOption($$);
71 # Defined in VCSUtils.
72 sub possiblyColored($$);
75 my $outputPath = "&STDOUT";
76 my $outputFormat = "text";
77 my $useColor = -t STDOUT;
78 my $unfilteredOutputPath = "build.log";
79 my $logUnfilteredOutput;
83 print STDERR <<__END__;
84 Usage: @{[ basename($0) ]} [options] buildlog1 [buildlog2 ...]
85 build-webkit | @{[ basename($0) ]} [options]
86 -h|--help Show this help message
88 -o|--output Path for output (default: STDOUT)
89 -f|--format Output format (default: $outputFormat)
91 html: Standalone HTML document
92 --[no-]color ANSI color output for text (default: on, if -o is STDOUT)
93 Unfiltered Logging Options:
94 -l|--log Save unfiltered output to file (see --log-file)
95 --logfile Path to save unfiltered output (implies --log, default: $unfilteredOutputPath)
100 my $getOptionsResult = GetOptions(
101 'h|help' => \$showHelp,
102 'o|output=s' => \$outputPath,
103 'f|format=s' => \&setOutputFormatOption,
104 'color!' => \$useColor,
105 'l|log' => \$logUnfilteredOutput,
106 'logfile=s' => \&setLogfileOption,
109 if (-t STDIN || $showHelp || !$getOptionsResult) {
113 open(OUTPUT_HANDLE, ">$outputPath") or die "Failed to open $outputPath : $!";
114 if ($logUnfilteredOutput) {
115 open(UNFILTERED_OUTPUT_HANDLE, ">$unfilteredOutputPath") or die "Failed to open $unfilteredOutputPath : $!";
118 print OUTPUT_HANDLE HTML_HEADER if ($outputFormat eq "html");
122 while (my $line = <>) {
123 print UNFILTERED_OUTPUT_HANDLE $line if $logUnfilteredOutput;
127 next if $line =~ /^\s*$/;
128 next if $line =~ /^Build settings from command line:/;
129 next if $line =~ /make: Nothing to be done for `all'\./;
130 next if $line =~ /^JavaScriptCore\/create_hash_table/;
131 next if $line =~ /JavaScriptCore.framework\/PrivateHeaders\/create_hash_table/;
132 next if $line =~ /^JavaScriptCore\/pcre\/dftables/;
133 next if $line =~ /^Creating hashtable for /;
134 next if $line =~ /^Wrote output to /;
135 next if $line =~ /^(touch|perl|cat|rm -f|bison|flex|python|\/usr\/bin\/g\+\+|gperf|echo|sed|if \[ \-f|WebCore\/generate-export-file) /;
136 next if $line =~ /^UNDOCUMENTED: /;
137 next if $line =~ /libtool.*has no symbols/;
138 next if $line =~ /^# Lower case all the values, as CSS values are case-insensitive$/;
139 next if $line =~ /^if sort /;
140 next if $line =~ /^ /;
141 next if $line =~ /^printf /;
142 next if $line =~ /^offlineasm: Nothing changed/;
143 next if $line =~ /^Showing first/;
145 if ($line =~ /^={10}/) {
146 printLine($line, STYLE_SUCCESS);
148 } elsif ($line =~ /^===/) {
149 printLine($line, STYLE_HEADER);
150 } elsif ($line =~ /Checking Dependencies|Check dependencies/) {
151 printLine($line, STYLE_PLAIN);
152 } elsif ($line =~ /\*\* BUILD SUCCEEDED \*\*/) {
153 printLine("Build Succeeded", STYLE_SUCCESS);
154 } elsif ($line =~ /^(PhaseScriptExecution|CompileC|Distributed-CompileC|Ld|PBXCp|CpResource|CopyPNGFile|CopyTiffFile|CpHeader|Processing|ProcessInfoPlistFile|ProcessPCH|ProcessPCH\+\+|Touch|Libtool|CopyStringsFile|Mig|CreateUniversalBinary|Analyze|ProcessProductPackaging|CodeSign|SymLink|Updating|CompileXIB|StripNIB|CopyPlistFile|GenerateDSYMFile) ("[^"]+"|\S+)?/) {
155 my ($command, $path) = ($1, basename($2));
157 printLine("$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 message.*(header|receiver) for (\S+)\.\.\./) {
164 my ($command, $path) = ($1, basename($2));
165 printLine("Generating message $command $path", STYLE_PLAIN);
166 } elsif ($line =~ /^(\S+\/cc).*?(\S+)\.(out|exp)/) {
167 my ($command, $path) = (basename($1), basename($2));
168 printLine("$command $path", STYLE_PLAIN);
170 # This only gets hit if stderr is redirected to stdout.
171 if ($line =~ /\*\* BUILD FAILED \*\*/) {
174 printLine($line, $buildFinished ? STYLE_SUCCESS : STYLE_ALERT);
178 print OUTPUT_HANDLE HTML_FOOTER if ($outputFormat eq "html");
180 close(OUTPUT_HANDLE);
181 close(UNFILTERED_OUTPUT_HANDLE) if ($logUnfilteredOutput);
187 my ($line, $style) = @_;
189 if ($outputFormat eq "html") {
190 $line = escapeHTML($line);
191 if ($style == STYLE_HEADER) { print OUTPUT_HANDLE "<h2>$line</h2>"; }
192 elsif ($style == STYLE_SUCCESS) { print OUTPUT_HANDLE "<p class=\"success\">$line</p>"; }
193 elsif ($style == STYLE_ALERT) { print OUTPUT_HANDLE "<p class=\"alert\">$line</p>"; }
194 else { print OUTPUT_HANDLE "<p>$line</p>"; }
197 my $colors = "reset";
198 if ($style == STYLE_HEADER) { $colors = "blue"; }
199 if ($style == STYLE_SUCCESS) { $colors = "green"; }
200 if ($style == STYLE_ALERT) { $colors = "red"; }
201 print OUTPUT_HANDLE possiblyColored($colors, $line);
203 print OUTPUT_HANDLE $line;
206 print OUTPUT_HANDLE "\n";
209 sub setLogfileOption($$)
211 my ($opt, $value) = @_;
212 $unfilteredOutputPath = $value;
213 $logUnfilteredOutput = 1;
216 sub setOutputFormatOption($$)
218 my ($opt, $value) = @_;
220 if ($value ne "html" && $value ne "text") {
221 die "The $opt option must be either \"html\" or \"text\"";
223 $outputFormat = $value;