kazeits has asked for the wisdom of the Perl Monks concerning the following question:

I am working on porting an open source perl program to windows and I think I have only one hurdle left to get over. The tool calls gcov to do some analysis and produce and output file that it brings in. From the command line I can invoke gcov like:
gcov c:/path/to/file.gcda -o relative/path/to/source -b
gcov then produces a .gcov file ./file.cpp.gcov using the following code:
$gcov_error = system_no_output(1, $gcov_tool, $da_filename, "-o", $object_dir, "-b"); sub system_no_output($@) { my $mode = shift; my $result; local *OLD_STDERR; local *OLD_STDOUT; # Save old stdout and stderr handles ($mode & 1) && open(OLD_STDOUT, ">>&STDOUT"); ($mode & 2) && open(OLD_STDERR, ">>&STDERR"); # Redirect to /dev/null ($mode & 1) && open(STDOUT, ">/dev/null"); ($mode & 2) && open(STDERR, ">/dev/null"); system(@_); $result = $?; # Close redirected handles ($mode & 1) && close(STDOUT); ($mode & 2) && close(STDERR); # Restore old handles ($mode & 1) && open(STDOUT, ">>&OLD_STDOUT"); ($mode & 2) && open(STDERR, ">>&OLD_STDERR"); return $result; }
gcov all of a sudden end up creating a file called ./relative#path#to#source#file.cpp.gcov What is the difference between running this on the command line and calling system? I know that perl will try and parse it through the command line if there is only 1 parameter.. however there is always more. at first I thought it was a gcov bug but I can run it manually.

update: I found the issue. There was a branch in the code that I was unaware I was taking. Apparently the '--preserve-paths' option in my windows build of was causing the file name mangling.

Replies are listed 'Best First'.
Re: system() Creating Different Results than Commandline Operation.
by BrowserUk (Patriarch) on Apr 06, 2009 at 17:05 UTC

    One problem, maybe unrelated to your symptoms but a problem anyway, is that '/dev/null' doesn't exist on windows.

    A simple system( "gcov c:/path/to/file.gcda -o relative/path/to/source -b 2>&1 >nul" ); would achieve your goal without all the faffing around.

    If you're wedded to rolling your own redirection, then what do you get if you try:

    $gcov_error = system_no_output( 1, 'perl.exe', '-le"print qq[>$_<] for @ARGV"' $da_filename, "-o", $object_dir, "-b" );

    The idea being to isolate whether it is the arguments being passed to the executable that are being screwed with, or the command itself that is misinterpreting them.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I tried the code below however I am unsure what I should be getting out of it. nothing is being printed out and I fear its due to the very nature of system_no_output.
      $gcov_error = system_no_output( 1, 'perl.exe', '-le"print qq[>$_<] for @ARGV"' $da_filename, "-o", $object_dir, "-b" );
      I have no preference one way or the other of how the command executed. system_no_output is merely code I am trying to port at the moment.
Re: system() Creating Different Results than Commandline Operation.
by ikegami (Patriarch) on Apr 06, 2009 at 17:09 UTC
    I don't how Perl could possibly do that. If I use
    my $gcov_tool = 'gcov'; my $da_filename = 'c:/path/to/file.gcda'; my $object_dir = 'relative/path/to/source'; $gcov_error = system_no_output(0, 'echo', $gcov_tool, $da_filename, "- +o", $object_dir, "-b");
    I get
    gcov c:/path/to/file.gcda -o relative/path/to/source -b
Re: system() Creating Different Results than Commandline Operation.
by ikegami (Patriarch) on Apr 06, 2009 at 17:17 UTC

    By the way, what's with ">/dev/null" on Windows? That should be ">nul".

    It's actually simpler to make it portable:

    sub system_no_output { my $mode = shift; open(my $chld_in, '<&', *STDIN) or die($!); my $chld_out = '>&STDOUT'; my $chld_err = '>&STDERR'; open($chld_out=undef, '>', devnull()) or die($!) if $mode & 1; open($chld_err=undef, '>', devnull()) or die($!) if $mode & 2; my $pid = open3($chld_in, $chld_out, $chld_err, @_) or die($!); return waitpid($pid, 0); }
      due to major changes to gcov over versions it needs to be opened to see what version is installed. the code makes a call to:
      if (system_no_output(3, $gcov_tool, "--help") == -1)
      using your solution to rewrite system_no_output seems to hang waiting for gcov to return. I don't understand why.

        -1 is not a valid value for $?, so it's a bug to expect system_no_output to return -1.

        If you want -1 when system fails and $? otherwise, you want:

        # Your version $result = system(@_);
        # My version my $pid = open3($chld_in, $chld_out, $chld_err, @_) or return -1;

        your solution to rewrite system_no_output seems to hang waiting for gcov to return

        system waits for the child to return, so I did the same.

Re: system() Creating Different Results than Commandline Operation.
by Anonymous Monk on Apr 06, 2009 at 17:09 UTC
    1) you're opening /dev/null on windows
    C:\>perl -MFile::Spec -e"die File::Spec->devnull nul at -e line 1.
    2)
    print " ====DEBUGGING gcov_tool ( $gcov_tool ) da_filename( $da_filename ) object_dir ( $object_dir ) ====DEBUGGING "