3 ### THIS IS DESIGNED TO BE RUN BY MAKE! DO NOT RUN FROM THE SHELL (because it MIGHT sigterm the shell)! ###
6 use warnings FATAL => qw(all);
10 # Runs the compiler, passing it the given arguments.
11 # Filters select output from the compiler's standard error channel and
12 # can take different actions as a result.
14 # NOTE: this is *NOT* a hash (sadly: a hash would stringize all the regexes and thus render them useless, plus you can't index a hash based on regexes anyway)
15 # even though we use the => in it.
17 # The subs are passed the message, and anything the regex captured.
19 my $cc = shift(@ARGV);
22 [ qr/^(.*) warning: cannot pass objects of non-POD type `(.*)' through `\.\.\.'; call will abort at runtime/ => sub {
23 my ($msg, $where, $type) = @_;
24 my $errstr = "$where error: cannot pass objects of non-POD type `$type' through `...'\n";
25 if ($type =~ m/::string/) {
26 $errstr .= "$where (Did you forget to call c_str()?)\n";
31 [ qr/^.* warning: / => sub {
33 print STDERR "\e[33;1m$msg\e[0m\n";
36 [ qr/^.* error: / => sub {
38 print STDERR "An error occured when executing:\e[37;1m $cc " . join(' ', @ARGV) . "\n";
39 print STDERR "\e[31;1m$msg\e[0m\n";
45 my ($r_stderr, $w_stderr);
57 if (!defined($cc) || $cc eq "") {
58 die "Compiler not specified!\n";
61 pipe($r_stderr, $w_stderr) or die "pipe stderr: $!\n";
65 die "Cannot fork to start gcc! $!\n" unless defined($pid);
69 print "\t\e[1;32mBUILD:\e[0m\t\t$name\n" unless $name eq "";
72 # Parent - Close child-side pipes.
74 # Close STDIN to ensure no conflicts with child.
76 # Now read each line of stderr
77 LINE: while (defined(my $line = <$r_stderr>)) {
79 for my $filter (@msgfilters) {
81 if (@caps = ($line =~ $filter->[0])) {
84 $filter->[1]->($line, @caps);
93 print STDERR "$line\n";
98 # Simulate the same exit, so make gets the right termination info.
99 if (POSIX::WIFSIGNALED($exit)) {
100 # Make won't get the right termination info (it gets ours, not the compiler's), so we must tell the user what really happened ourselves!
101 print STDERR "$cc killed by signal " . POSIX::WTERMSIGN($exit) . "\n";
102 kill "TERM", getppid(); # Needed for bsd make.
106 if (POSIX::WEXITSTATUS($exit) == 0) {
108 kill "TERM", getppid(); # Needed for bsd make.
113 exit POSIX::WEXITSTATUS($exit);
117 # Child - Close parent-side pipes.
120 open STDERR, ">&", $w_stderr or die "Cannot divert STDERR: $!\n";
122 exec { $cc } $cc, @ARGV;
123 die "exec $cc: $!\n";