bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in $(shell ...) I can't understand


From: Paul Smith
Subject: Bug in $(shell ...) I can't understand
Date: Sun, 06 Feb 2022 11:23:03 -0500
User-agent: Evolution 3.42.3 (flatpak git)

OK, someone posted a question to SO and that led me to an hour or more
of banging my head against a wall trying to understand what's
happening... and I can't.

The problem is that the user would like to invoke $(shell ...) and
capture errors, even errors that the program being run doesn't exist. 
The shell function only captures stdout, not stderr.  This simple idea
won't work of course:

  out := $(shell bad-program 2>&1)
  $(info out = $(out))

  $ make
  /bin/sh: bad-program: not found
  out =

because this redirects the output of the bad-program, but it's the
shell printing the error not the program.  So I suggested this:

  out := $(shell $(SHELL) -c 'bad-program' 2>&1)
  $(info out = $(out))

This SHOULD work: the outer shell is invoking a sub-shell with the sub-
shell's stderr redirected to its stdout, then the subshell will print
the not found error to its stderr (redirected to stdout).

But it DOES NOT WORK!

  $ make
  /bin/sh: bad-program: not found
  out =

What is happening here?!?!  I wrote a little C program to verify my
thinking:

/* ----- */
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char** argv)
{
    char *args[4] = {"/bin/sh", "-c",
                     "/bin/sh -c bad-program 2>&1", NULL};

    int pid = fork();
    if (pid == 0) {
        execv(args[0], args);
    } else {
        int st;
        waitpid(pid, &st, 0);
    }

    return 0;
}
/* ----- */

But, this works as expected.  Something make is doing is causing
problems here.  I tried building both with and without posix_spawn and
both behave the same so it's nothing like that.

If you force the sub-shell to create its own subshell, then it works! 
This works:

  out := $(shell $(SHELL) -c 'bad-program | cat' 2>&1)
  $(info out = $(out))

  $ make
  out = /bin/sh: bad-program: not found




reply via email to

[Prev in Thread] Current Thread [Next in Thread]