blob: cf671569e0296dadc5c8cd23138640f871bfcfe3 [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001#
2#//===----------------------------------------------------------------------===//
3#//
4#// The LLVM Compiler Infrastructure
5#//
6#// This file is dual licensed under the MIT and the University of Illinois Open
7#// Source Licenses. See LICENSE.txt for details.
8#//
9#//===----------------------------------------------------------------------===//
10#
11package Build;
12
13use strict;
14use warnings;
15
16use Cwd qw{};
17
18use LibOMP;
19use tools;
20use Uname;
21use Platform ":vars";
22
23my $host = Uname::host_name();
24my $root = $ENV{ LIBOMP_WORK };
25my $tmp = $ENV{ LIBOMP_TMP };
26my $out = $ENV{ LIBOMP_EXPORTS };
27
28my @jobs;
29our $start = time();
30
31# --------------------------------------------------------------------------------------------------
32# Helper functions.
33# --------------------------------------------------------------------------------------------------
34
35# tstr -- Time string. Returns string "yyyy-dd-mm hh:mm:ss UTC".
36sub tstr(;$) {
37 my ( $time ) = @_;
38 if ( not defined( $time ) ) {
39 $time = time();
40 }; # if
41 my ( $sec, $min, $hour, $day, $month, $year ) = gmtime( $time );
42 $month += 1;
43 $year += 1900;
44 my $str = sprintf( "%04d-%02d-%02d %02d:%02d:%02d UTC", $year, $month, $day, $hour, $min, $sec );
45 return $str;
46}; # sub tstr
47
48# dstr -- Duration string. Returns string "hh:mm:ss".
49sub dstr($) {
50 # Get time in seconds and format it as time in hours, minutes, seconds.
51 my ( $sec ) = @_;
52 my ( $h, $m, $s );
53 $h = int( $sec / 3600 );
54 $sec = $sec - $h * 3600;
55 $m = int( $sec / 60 );
56 $sec = $sec - $m * 60;
57 $s = int( $sec );
58 $sec = $sec - $s;
59 return sprintf( "%02d:%02d:%02d", $h, $m, $s );
60}; # sub dstr
61
62# rstr -- Result string.
63sub rstr($) {
64 my ( $rc ) = @_;
65 return ( $rc == 0 ? "+++ Success +++" : "--- Failure ---" );
66}; # sub rstr
67
68sub shorter($;$) {
69 # Return shorter variant of path -- either absolute or relative.
70 my ( $path, $base ) = @_;
71 my $abs = abs_path( $path );
72 my $rel = rel_path( $path, $base );
73 if ( $rel eq "" ) {
74 $rel = ".";
75 }; # if
76 $path = ( length( $rel ) < length( $abs ) ? $rel : $abs );
77 if ( $target_os eq "win" ) {
78 $path =~ s{\\}{/}g;
79 }; # if
80 return $path;
81}; # sub shorter
82
83sub tee($$) {
84
85 my ( $action, $file ) = @_;
86 my $pid = 0;
87
88 my $save_stdout = Symbol::gensym();
89 my $save_stderr = Symbol::gensym();
90
91 # --- redirect stdout ---
92 STDOUT->flush();
93 # Save stdout in $save_stdout.
94 open( $save_stdout, ">&" . STDOUT->fileno() )
95 or die( "Cannot dup filehandle: $!; stopped" );
96 # Redirect stdout to tee or to file.
97 if ( $tools::verbose ) {
98 $pid = open( STDOUT, "| tee -a \"$file\"" )
99 or die "Cannot open pipe to \"tee\": $!; stopped";
100 } else {
101 open( STDOUT, ">>$file" )
102 or die "Cannot open file \"$file\" for writing: $!; stopped";
103 }; # if
104
105 # --- redirect stderr ---
106 STDERR->flush();
107 # Save stderr in $save_stderr.
108 open( $save_stderr, ">&" . STDERR->fileno() )
109 or die( "Cannot dup filehandle: $!; stopped" );
110 # Redirect stderr to stdout.
111 open( STDERR, ">&" . STDOUT->fileno() )
112 or die( "Cannot dup filehandle: $!; stopped" );
113
114 # Perform actions.
115 $action->();
116
117 # --- restore stderr ---
118 STDERR->flush();
119 # Restore stderr from $save_stderr.
120 open( STDERR, ">&" . $save_stderr->fileno() )
121 or die( "Cannot dup filehandle: $!; stopped" );
122 # Close $save_stderr.
123 $save_stderr->close() or die ( "Cannot close filehandle: $!; stopped" );
124
125 # --- restore stdout ---
126 STDOUT->flush();
127 # Restore stdout from $save_stdout.
128 open( STDOUT, ">&" . $save_stdout->fileno() )
129 or die( "Cannot dup filehandle: $!; stopped" );
130 # Close $save_stdout.
131 $save_stdout->close() or die ( "Cannot close filehandle: $!; stopped" );
132
133 # Wait for the child tee process, otherwise output of make and build.pl interleaves.
134 if ( $pid != 0 ) {
135 waitpid( $pid, 0 );
136 }; # if
137
138}; # sub tee
139
140sub log_it($$@) {
141 my ( $title, $format, @args ) = @_;
142 my $message = sprintf( $format, @args );
143 my $progress = cat_file( $tmp, sprintf( "%s-%s.log", $target_platform, Uname::host_name() ) );
144 if ( $title ne "" and $message ne "" ) {
145 my $line = sprintf( "%-15s : %s\n", $title, $message );
146 info( $line );
147 write_file( $progress, tstr() . ": " . $line, -append => 1 );
148 } else {
149 write_file( $progress, "\n", -append => 1 );
150 }; # if
151}; # sub log_it
152
153sub progress($$@) {
154 my ( $title, $format, @args ) = @_;
155 log_it( $title, $format, @args );
156}; # sub progress
157
158sub summary() {
159 my $total = @jobs;
160 my $success = 0;
161 my $finish = time();
162 foreach my $job ( @jobs ) {
163 my ( $build_dir, $rc ) = ( $job->{ build_dir }, $job->{ rc } );
164 progress( rstr( $rc ), "%s", $build_dir );
165 if ( $rc == 0 ) {
166 ++ $success;
167 }; # if
168 }; # foreach $job
169 my $failure = $total - $success;
170 progress( "Successes", "%3d of %3d", $success, $total );
171 progress( "Failures", "%3d of %3d", $failure, $total );
172 progress( "Time elapsed", " %s", dstr( $finish - $start ) );
173 progress( "Overall result", "%s", rstr( $failure ) );
174 return $failure;
175}; # sub summary
176
177# --------------------------------------------------------------------------------------------------
178# Worker functions.
179# --------------------------------------------------------------------------------------------------
180
181sub init() {
182 make_dir( $tmp );
183}; # sub init
184
185sub clean(@) {
186 # Clean directories.
187 my ( @dirs ) = @_;
188 my $exit = 0;
189 # Mimisc makefile -- print a command.
190 print( "rm -f -r " . join( " ", map( shorter( $_ ) . "/*", @dirs ) ) . "\n" );
191 $exit =
192 execute(
193 [ $^X, cat_file( $ENV{ LIBOMP_WORK }, "tools", "clean-dir.pl" ), @dirs ],
194 -ignore_status => 1,
195 ( $tools::verbose ? () : ( -stdout => undef, -stderr => "" ) ),
196 );
197 return $exit;
198}; # sub clean
199
200sub make($$$) {
201 # Change dir to build one and run make.
202 my ( $job, $clean, $marker ) = @_;
203 my $dir = $job->{ build_dir };
204 my $makefile = $job->{ makefile };
205 my $args = $job->{ make_args };
206 my $cwd = Cwd::cwd();
207 my $width = -10;
208
209 my $exit;
210 $dir = cat_dir( $tmp, $dir );
211 make_dir( $dir );
212 change_dir( $dir );
213
214 my $actions =
215 sub {
216 my $start = time();
217 $makefile = shorter( $makefile );
218 print( "-" x 79, "\n" );
219 printf( "%${width}s: %s\n", "Started", tstr( $start ) );
220 printf( "%${width}s: %s\n", "Root dir", $root );
221 printf( "%${width}s: %s\n", "Build dir", shorter( $dir, $root ) );
222 printf( "%${width}s: %s\n", "Makefile", $makefile );
223 print( "-" x 79, "\n" );
224 {
225 # Use shorter LIBOMP_WORK to have shorter command lines.
226 # Note: Some tools may not work if current dir is changed.
227 local $ENV{ LIBOMP_WORK } = shorter( $ENV{ LIBOMP_WORK } );
228 $exit =
229 execute(
230 [
231 "make",
232 "-r",
233 "-f", $makefile,
234 "arch=" . $target_arch,
235 "marker=$marker",
236 @$args
237 ],
238 -ignore_status => 1
239 );
240 if ( $clean and $exit == 0 ) {
241 $exit = clean( $dir );
242 }; # if
243 }
244 my $finish = time();
245 print( "-" x 79, "\n" );
246 printf( "%${width}s: %s\n", "Finished", tstr( $finish ) );
247 printf( "%${width}s: %s\n", "Elapsed", dstr( $finish - $start ) );
248 printf( "%${width}s: %s\n", "Result", rstr( $exit ) );
249 print( "-" x 79, "\n" );
250 print( "\n" );
251 }; # sub
252 tee( $actions, "build.log" );
253
254 change_dir( $cwd );
255
256 # Save completed job to be able print summary later.
257 $job->{ rc } = $exit;
258 push( @jobs, $job );
259
260 return $exit;
261
262}; # sub make
263
2641;