From: Andrew Gaffney [mailto:[EMAIL PROTECTED] Sent: Monday, 23 February 2004 12:35 AM
To: David le Blanc
Cc: [EMAIL PROTECTED]
Subject: Re: parsing Makefiles
David le Blanc wrote:
From: Andrew Gaffney [mailto:[EMAIL PROTECTED] Sent: Sunday, 22 February 2004 6:09 PM
To: David le Blanc
Cc: [EMAIL PROTECTED]
Subject: Re: parsing Makefiles
David le Blanc wrote:
I've come up with some *simple* code that seems to work:
#!/usr/bin/perl
use strict; use warnings;
$| = 1; my $total = `make -n | wc -l`; my ($count, $line); open MAKE, "make |"; foreach $line (<MAKE>) { $count++; my $percent = int(($count / $total) * 100); print "..$percent"; }
You may find that the 'MAKE' file handle is buffered by the make application.
I order to ensure 'make' doesn't buffer its output, you
need to run it
in its
own pseudo-terminal. The Expect module may be able to
help, since it
runs
apps in pseudo-terminals, or someone else may offer a
better solution.
Its not the 'make' output that's being buffered. That doesn't get printed at all. Its my output that does appear until the whole run is done.
Ok, Lets break down what is really going on here.
Your loop construct:
foreach $line (<MAKE>) { .. print stuff ..
}
is looping BASED ON THE OUTPUT of the make command.
Since the MAKE COMMAND OUTPUT is being buffered by the make command,
you will find that NOTHING arrives in the 'foreach' loop until the
entire make has complete and FLUSHED its output.
Hence, if you want to print output as the MAKE COMMAND
OUTPUT arrives,
you must make sure the COMMAND OUTPUT arrives in a timely manner.. I.e. unbuffered.
I understand. I modified my code to verify this:
#!/usr/bin/perl
use strict; use warnings;
#$| = 1; my $total = `make -n | wc -l`; print "$total\n"; my ($count, $line); open MAKE, "make |"; foreach $line (<MAKE>) { $count++; my $percent = int(($count / $total) * 100); # print "..$percent"; print $line; }
This waited until the end to print all the output. Although, if I do something like 'make | less' on the command line, the output is not buffered. So, is Perl buffering the output from MAKE in this case?
Close, but not quite. perl is handing the data to your script as soon as it arrives from the make command. The make command on the otherhand has realised you are not using a TTY, but are in fact directing the output to a pipe or file, so it buffers the contents internally.
That doesn't make sense. When it pipes through less, as far as 'make' knows, its not outputting to a TTY anymore. Piping output through Perl should be the same as piping to less as far as 'make' is concerned.
Try the following.
In one window, touch 'make.log', and then run 'tail -f make.log'
In another window, run 'make >> make.log'
If the output appears as it does when using less, then it is perl that is buffering the output, so add to your script:
The output appears just as it did with 'make | less'.
# at the top use IO::Handle;
# after the open MAKE->autoflush(0);
This doesn't work. Same results still. I double-checked that Perl wasn't buffering my output by having it print localtime() with each output. I get ~30 lines of the same time. Does Perl try to read the entire 'file' in before it sticks it into the array? This would make sense. Perl could be waiting for the 'file' to 'close' ('make' to finish running) before it starts chopping up the output.
-- Andrew Gaffney Network Administrator Skyline Aeronautics, LLC. 636-357-1548
-- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>